diff --git a/README.md b/README.md index 704831c..5e69e96 100644 --- a/README.md +++ b/README.md @@ -25,6 +25,9 @@ yarn add use-mcp - 🔄 Automatic connection management with reconnection and retries - 🔐 OAuth authentication flow handling with popup and fallback support - 📦 Simple React hook interface for MCP integration +- 🧰 Full support for MCP tools, resources, and prompts +- 📄 Access server resources and read their contents +- 💬 Use server-provided prompt templates - 🧰 TypeScript types for editor assistance and type checking - 📝 Comprehensive logging for debugging - 🌐 Works with both HTTP and SSE (Server-Sent Events) transports @@ -38,8 +41,12 @@ function MyAIComponent() { const { state, // Connection state: 'discovering' | 'pending_auth' | 'authenticating' | 'connecting' | 'loading' | 'ready' | 'failed' tools, // Available tools from MCP server + resources, // Available resources from MCP server + prompts, // Available prompts from MCP server error, // Error message if connection failed callTool, // Function to call tools on the MCP server + readResource, // Function to read resource contents + getPrompt, // Function to get prompt messages retry, // Retry connection manually authenticate, // Manually trigger authentication clearStorage, // Clear stored tokens and credentials @@ -83,6 +90,32 @@ function MyAIComponent() { ))} + + {/* Example: Display and read resources */} + {resources.length > 0 && ( +
+

Resources: {resources.length}

+ +
+ )} + + {/* Example: Use prompts */} + {prompts.length > 0 && ( +
+

Prompts: {prompts.length}

+ +
+ )} ) } @@ -176,10 +209,17 @@ function useMcp(options: UseMcpOptions): UseMcpResult |----------|------|-------------| | `state` | `string` | Current connection state: 'discovering', 'pending_auth', 'authenticating', 'connecting', 'loading', 'ready', 'failed' | | `tools` | `Tool[]` | Available tools from the MCP server | +| `resources` | `Resource[]` | Available resources from the MCP server | +| `resourceTemplates` | `ResourceTemplate[]` | Available resource templates from the MCP server | +| `prompts` | `Prompt[]` | Available prompts from the MCP server | | `error` | `string \| undefined` | Error message if connection failed | | `authUrl` | `string \| undefined` | Manual authentication URL if popup is blocked | | `log` | `{ level: 'debug' \| 'info' \| 'warn' \| 'error'; message: string; timestamp: number }[]` | Array of log messages | | `callTool` | `(name: string, args?: Record) => Promise` | Function to call a tool on the MCP server | +| `listResources` | `() => Promise` | Refresh the list of available resources | +| `readResource` | `(uri: string) => Promise<{ contents: Array<...> }>` | Read the contents of a specific resource | +| `listPrompts` | `() => Promise` | Refresh the list of available prompts | +| `getPrompt` | `(name: string, args?: Record) => Promise<{ messages: Array<...> }>` | Get a specific prompt with optional arguments | | `retry` | `() => void` | Manually attempt to reconnect | | `disconnect` | `() => void` | Disconnect from the MCP server | | `authenticate` | `() => void` | Manually trigger authentication | diff --git a/examples/inspector/README.md b/examples/inspector/README.md index d137ed3..b29c779 100644 --- a/examples/inspector/README.md +++ b/examples/inspector/README.md @@ -6,6 +6,8 @@ A minimal demo showcasing the `use-mcp` React hook for connecting to Model Conte - Connect to any MCP server via URL - View available tools and their schemas +- Browse and read server resources +- Interact with server-provided prompts - Real-time connection status monitoring - Debug logging for troubleshooting - Clean, minimal UI focused on MCP functionality @@ -31,7 +33,7 @@ pnpm dev 3. Open your browser and navigate to the displayed local URL -4. Enter an MCP server URL to test the connection and explore available tools +4. Enter an MCP server URL to test the connection and explore available tools, resources, and prompts ## What This Demonstrates @@ -46,7 +48,17 @@ const connection = useMcp({ autoRetry: false }) -// Access connection.state, connection.tools, connection.error, etc. +// Access connection.state, connection.tools, connection.resources, +// connection.prompts, connection.error, etc. ``` -The `McpServers` component wraps this hook to provide a complete UI for server management and tool inspection. +The `McpServers` component wraps this hook to provide a complete UI for server management, tool inspection, resource browsing, and prompt interaction. + +## Supported MCP Features + +- **Tools**: Execute server-provided tools with custom arguments and view results +- **Resources**: Browse available resources and read their contents (text or binary) +- **Resource Templates**: View dynamic resource templates with URI patterns +- **Prompts**: Interact with server prompts, provide arguments, and view generated messages + +Note: Not all MCP servers implement all features. The inspector will gracefully handle servers that only support a subset of the MCP specification. diff --git a/examples/inspector/src/components/McpServers.tsx b/examples/inspector/src/components/McpServers.tsx index 95b52fc..7f397c6 100644 --- a/examples/inspector/src/components/McpServers.tsx +++ b/examples/inspector/src/components/McpServers.tsx @@ -60,13 +60,11 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) retry: () => {}, disconnect: () => {}, authenticate: () => Promise.resolve(undefined), - callTool: (_name: string, _args?: Record) => - Promise.resolve(undefined), + callTool: (_name: string, _args?: Record) => Promise.resolve(undefined), listResources: () => Promise.resolve(), readResource: (_uri: string) => Promise.resolve({ contents: [] }), listPrompts: () => Promise.resolve(), - getPrompt: (_name: string, _args?: Record) => - Promise.resolve({ messages: [] }), + getPrompt: (_name: string, _args?: Record) => Promise.resolve({ messages: [] }), clearStorage: () => {}, }) const [toolForms, setToolForms] = useState>>({}) @@ -118,13 +116,11 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) retry: () => {}, disconnect: () => {}, authenticate: () => Promise.resolve(undefined), - callTool: (_name: string, _args?: Record) => - Promise.resolve(undefined), + callTool: (_name: string, _args?: Record) => Promise.resolve(undefined), listResources: () => Promise.resolve(), readResource: (_uri: string) => Promise.resolve({ contents: [] }), listPrompts: () => Promise.resolve(), - getPrompt: (_name: string, _args?: Record) => - Promise.resolve({ messages: [] }), + getPrompt: (_name: string, _args?: Record) => Promise.resolve({ messages: [] }), clearStorage: () => {}, }) } @@ -495,10 +491,8 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) {/* Available Resources section */}
-

- Available Resources ({resources.length + resourceTemplates.length}) -

- +

Available Resources ({resources.length + resourceTemplates.length})

+ {resources.length === 0 && resourceTemplates.length === 0 ? (
No resources available. Connect to an MCP server to see available resources. @@ -509,13 +503,13 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) {resources.map((resource: Resource, index: number) => { const isExpanded = expandedResources[resource.uri] || false const contents = resourceContents[resource.uri] - + return (
- {resource.description && ( -

{resource.description}

- )} + {resource.description &&

{resource.description}

}

{resource.uri}

- {resource.mimeType && ( - ({resource.mimeType}) - )} + {resource.mimeType && ({resource.mimeType})}
- + {isExpanded && (
- + {contents && (
{contents.error ? ( @@ -579,7 +569,7 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[])
) })} - + {/* Resource Templates */} {resourceTemplates.map((template: ResourceTemplate, index: number) => (
@@ -589,13 +579,9 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[])

{template.name}

Template
- {template.description && ( -

{template.description}

- )} + {template.description &&

{template.description}

}

{template.uriTemplate}

- {template.mimeType && ( - ({template.mimeType}) - )} + {template.mimeType && ({template.mimeType})}
))} @@ -605,10 +591,8 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) {/* Available Prompts section */}
-

- Available Prompts ({prompts.length}) -

- +

Available Prompts ({prompts.length})

+ {prompts.length === 0 ? (
No prompts available. Connect to an MCP server to see available prompts. @@ -619,13 +603,13 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) const isExpanded = expandedPrompts[prompt.name] || false const result = promptResults[prompt.name] const args = promptArgs[prompt.name] || {} - + return (
- {prompt.description && ( -

{prompt.description}

- )} + {prompt.description &&

{prompt.description}

}
- + {isExpanded && (
{/* Prompt Arguments */} @@ -652,42 +634,42 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[]) setPromptArgs(prev => ({ - ...prev, - [prompt.name]: { - ...prev[prompt.name], - [arg.name]: e.target.value - } - }))} + onChange={(e) => + setPromptArgs((prev) => ({ + ...prev, + [prompt.name]: { + ...prev[prompt.name], + [arg.name]: e.target.value, + }, + })) + } placeholder={arg.description || `Enter ${arg.name}`} />
))}
)} - + - + {result && (
{result.error ? ( @@ -699,9 +681,7 @@ export function McpServers({ onToolsUpdate }: { onToolsUpdate?: (tools: Tool[])
Messages:
{result.messages?.map((message: any, idx: number) => (
-
- {message.role}: -
+
{message.role}:
                                         {message.content.text || JSON.stringify(message.content, null, 2)}
                                       
diff --git a/src/react/README.md b/src/react/README.md index 3e15c47..f523ea5 100644 --- a/src/react/README.md +++ b/src/react/README.md @@ -23,7 +23,7 @@ The useMcp hook manages the connection to an MCP server, handles authentication ```tsx import { useMcp } from 'use-mcp' // Optional: Import types if needed -import type { UseMcpOptions, UseMcpResult, Tool } from 'use-mcp' +import type { UseMcpOptions, UseMcpResult, Tool, Resource, ResourceTemplate, Prompt } from 'use-mcp' ``` ## Usage @@ -101,7 +101,12 @@ function MyChatComponent() {
)} {mcp.state === 'authenticating' &&

Waiting for authentication...

} - {mcp.state === 'ready' &&

Connected! Tools available: {mcp.tools.length}

} + {mcp.state === 'ready' && ( +

+ Connected! Tools: {mcp.tools.length}, Resources: {mcp.resources.length + mcp.resourceTemplates.length}, + Prompts: {mcp.prompts.length} +

+ )} {/* Your Chat UI */}
@@ -140,6 +145,52 @@ function MyChatComponent() { + + {/* Example: Working with Resources */} + {mcp.state === 'ready' && mcp.resources.length > 0 && ( +
+

Available Resources:

+ {mcp.resources.map((resource) => ( +
+ {resource.name} + +
+ ))} +
+ )} + + {/* Example: Working with Prompts */} + {mcp.state === 'ready' && mcp.prompts.length > 0 && ( +
+

Available Prompts:

+ {mcp.prompts.map((prompt) => ( +
+ {prompt.name} + +
+ ))} +
+ )}
) } @@ -163,11 +214,18 @@ export default MyChatComponent ### Hook Return Value (UseMcpResult) - tools: An array of Tool objects provided by the server. Empty until state is 'ready'. +- resources: An array of Resource objects representing data available from the server. +- resourceTemplates: An array of ResourceTemplate objects representing dynamic resources available from the server. +- prompts: An array of Prompt objects representing reusable prompt templates from the server. - state: The current connection state ('discovering', 'authenticating', 'connecting', 'loading', 'ready', 'failed'). Use this to conditionally render UI or enable/disable features. - error: An error message if state is 'failed'. - authUrl: If authentication is required and the popup was potentially blocked, this URL string can be used to let the user manually open the auth page (e.g., ...). - log: An array of log messages { level, message, timestamp }. Useful for debugging when debug option is true. - callTool(name, args): An async function to execute a tool on the MCP server. Throws an error if the client isn't ready or the call fails. +- listResources(): An async function to refresh the list of available resources. Returns void. +- readResource(uri): An async function to read the contents of a specific resource. Returns an object with a 'contents' array containing the resource data. +- listPrompts(): An async function to refresh the list of available prompts. Returns void. +- getPrompt(name, args): An async function to get a specific prompt with optional arguments. Returns an object with a 'messages' array containing the prompt messages. - retry(): Manually triggers a reconnection attempt if the state is 'failed'. - disconnect(): Disconnects the client from the server. - authenticate(): Manually attempts to start the authentication flow. Useful for triggering the popup via a user click if it was initially blocked.