npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@gary149/use-mcp

v0.1.3

Published

<div class="oranda-hide">

Readme

🦑 use-mcp 🦑

GitHub last commit  npm GitHub License

A lightweight client for connecting to Model Context Protocol (MCP) servers. Provides a React hook and a Svelte store adapter to simplify authentication and tool calling.

Try it out: Chat Demo | MCP Inspector | Cloudflare Workers AI Playground

Examples in this repo:

Installation

npm install @gary149/use-mcp
# or
pnpm add @gary149/use-mcp
# or
yarn add @gary149/use-mcp

Development

To run the development environment with the React examples and servers:

pnpm dev

This starts:

  • Inspector: http://localhost:5001 - MCP server debugging tool
  • Chat UI: http://localhost:5002 - Example chat interface
  • Hono MCP Server: http://localhost:5101 - Example MCP server
  • CF Agents MCP Server: http://localhost:5102 - Cloudflare Workers AI MCP server

Svelte inspector example:

cd examples/inspector-svelte
pnpm install
pnpm dev

Then open the local URL shown by Vite and connect to an MCP server (e.g. https://huggingface.co/mcp). The UI lists tools and provides input fields generated from each tool's JSON schema.

Testing

Integration tests are located in the test/ directory and run headlessly by default:

cd test && pnpm test              # Run tests headlessly (default)
cd test && pnpm test:headed       # Run tests with visible browser
cd test && pnpm test:watch        # Run tests in watch mode
cd test && pnpm test:ui           # Run tests with interactive UI

Features

  • 🔄 Automatic connection management with reconnection and retries
  • 🔐 OAuth authentication flow handling with popup and fallback support
  • 📦 Simple React hook and Svelte store adapters 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 (HTTP streaming recommended)

Quick Start (React)

import { useMcp } from '@gary149/use-mcp/react'

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
  } = useMcp({
    url: 'https://your-mcp-server.com',
    clientName: 'My App',
    autoReconnect: true,
  })

  // Handle different states
  if (state === 'failed') {
    return (
      <div>
        <p>Connection failed: {error}</p>
        <button onClick={retry}>Retry</button>
        <button onClick={authenticate}>Authenticate Manually</button>
      </div>
    )
  }

  if (state !== 'ready') {
    return <div>Connecting to AI service...</div>
  }

  // Use available tools
  const handleSearch = async () => {
    try {
      const result = await callTool('search', { query: 'example search' })
      console.log('Search results:', result)
    } catch (err) {
      console.error('Tool call failed:', err)
    }
  }

  return (
    <div>
      <h2>Available Tools: {tools.length}</h2>
      <ul>
        {tools.map(tool => (
          <li key={tool.name}>{tool.name}</li>
        ))}
      </ul>
      <button onClick={handleSearch}>Search</button>
      
      {/* Example: Display and read resources */}
      {resources.length > 0 && (
        <div>
          <h3>Resources: {resources.length}</h3>
          <button onClick={async () => {
            const content = await readResource(resources[0].uri)
            console.log('Resource content:', content)
          }}>
            Read First Resource
          </button>
        </div>
      )}
      
      {/* Example: Use prompts */}
      {prompts.length > 0 && (
        <div>
          <h3>Prompts: {prompts.length}</h3>
          <button onClick={async () => {
            const result = await getPrompt(prompts[0].name)
            console.log('Prompt messages:', result.messages)
          }}>
            Get First Prompt
          </button>
        </div>
      )}
    </div>
  )
}

Quick Start (Svelte/SvelteKit)

// src/lib/mcp.ts
import { browser } from '$app/environment'
import { createMcp } from '@gary149/use-mcp/svelte'

export const mcp = browser ? createMcp({
  url: 'https://your-mcp-server.com',
  clientName: 'My App',
  autoReconnect: true,
  // transportType: 'http', // recommended; SSE is legacy
}) : undefined
<!-- src/routes/+page.svelte -->
<script lang="ts">
  import { mcp } from '$lib/mcp'
</script>

{#if mcp}
  {#if $mcp.state === 'failed'}
    <p>Connection failed: {$mcp.error}</p>
    <button on:click={() => mcp.retry()}>Retry</button>
    <button on:click={() => mcp.authenticate()}>Authenticate Manually</button>
  {:else if $mcp.state !== 'ready'}
    <p>Connecting to AI service…</p>
  {:else}
    <h2>Available Tools: {$mcp.tools.length}</h2>
    <button on:click={() => mcp.callTool('search', { query: 'example search' })}>
      Search
    </button>
  {/if}
{:else}
  <p>Loading…</p>
{/if}

Setting Up OAuth Callback

To handle the OAuth authentication flow, you need to set up a callback endpoint in your app.

With React Router

// App.tsx with React Router
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import { useEffect } from 'react'
import { onMcpAuthorization } from '@gary149/use-mcp'

function OAuthCallback() {
  useEffect(() => {
    onMcpAuthorization()
  }, [])

  return (
    <div>
      <h1>Authenticating...</h1>
      <p>This window should close automatically.</p>
    </div>
  )
}

function App() {
  return (
    <Router>
      <Routes>
        <Route path="/oauth/callback" element={<OAuthCallback />} />
        <Route path="/" element={<YourMainComponent />} />
      </Routes>
    </Router>
  )
}

With Next.js Pages Router

// pages/oauth/callback.tsx
import { useEffect } from 'react'
import { onMcpAuthorization } from '@gary149/use-mcp'

export default function OAuthCallbackPage() {
  useEffect(() => {
    onMcpAuthorization()
  }, [])

  return (
    <div>
      <h1>Authenticating...</h1>
      <p>This window should close automatically.</p>
    </div>
  )
}

With SvelteKit

<!-- src/routes/oauth/callback/+page.svelte -->
<script lang="ts">
  import { onMount } from 'svelte'
  import { onMcpAuthorization } from '@gary149/use-mcp'
  onMount(() => onMcpAuthorization())
</script>

<h1>Authenticating…</h1>
<p>This window should close automatically.</p>

Note: When using HTTP streaming transport across origins, ensure your MCP server CORS configuration allows and exposes the Mcp-Session-Id header so the browser can maintain the session. If your OAuth callback is hosted on a different origin (e.g., auth subdomain), pass allowedOrigins: ['https://auth.example.com'] to createMcp(...) so the popup callback message is accepted.

API Reference

useMcp Hook

function useMcp(options: UseMcpOptions): UseMcpResult

Options

| Option | Type | Description | |--------|------|-------------| | url | string | Required. URL of your MCP server | | clientName | string | Name of your client for OAuth registration | | clientUri | string | URI of your client for OAuth registration | | callbackUrl | string | Custom callback URL for OAuth redirect (defaults to /oauth/callback on the current origin) | | storageKeyPrefix | string | Storage key prefix for OAuth data in localStorage (defaults to "mcp:auth") | | clientConfig | object | Custom configuration for the MCP client identity | | debug | boolean | Whether to enable verbose debug logging | | autoRetry | boolean \| number | Auto retry connection if initial connection fails, with delay in ms | | autoReconnect | boolean \| number | Auto reconnect if an established connection is lost, with delay in ms (default: 3000) | | transportType | 'auto' \| 'http' \| 'sse' | Transport type preference: 'auto' (HTTP with SSE fallback), 'http' (HTTP only), 'sse' (SSE only) (default: 'auto') | | preventAutoAuth | boolean | Prevent automatic authentication popup on initial connection (default: false) | | onPopupWindow | (url: string, features: string, window: Window \| null) => void | Callback invoked just after the authentication popup window is opened |

Return Value

| Property | Type | Description | |----------|------|-------------| | 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<string, unknown>) => Promise<any> | Function to call a tool on the MCP server | | listResources | () => Promise<void> | Refresh the list of available resources | | readResource | (uri: string) => Promise<{ contents: Array<...> }> | Read the contents of a specific resource | | listPrompts | () => Promise<void> | Refresh the list of available prompts | | getPrompt | (name: string, args?: Record<string, string>) => 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 | | clearStorage | () => void | Clear all stored authentication data |

License

MIT