- TypeScript 99.3%
- Shell 0.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
> When the assistant responds with a longer message including markdown markup, the UI renders it out but it ends up looking too spaced out. Can you investigate what library we're using to render the
mark down and whether it's possible to tweak the visual spacing to keep things a little bit tighter. I'm thinking in particular headings and lists as well as the overall line height is a touch too
big.
⏺ I'll investigate the markdown rendering library and spacing issues in your chat UI. Let me first explore the codebase to understand how markdown is being rendered.
⏺ Update Todos
⎿ ☐ Find and identify the markdown rendering library being used
☐ Analyze current CSS styling for markdown elements
☐ Adjust spacing for headings, lists, and line height
⏺ Search(pattern: "markdown|marked|remark|react-markdown", include: "*.json")
⎿ Found 1 file (ctrl+r to expand)
⏺ Search(pattern: "markdown|Markdown", include: "*.{js,jsx,ts,tsx}")
⎿ Found 2 files (ctrl+r to expand)
⏺ Search(pattern: "package.json")
⎿ Found 1 file (ctrl+r to expand)
⏺ Read(package.json)
⎿ Read 57 lines (ctrl+r to expand)
⏺ Read(src/components/messages/ChatMessage.tsx)
⎿ Read 54 lines (ctrl+r to expand)
⏺ Read(src/components/messages/AssistantMessage.tsx)
⎿ Read 32 lines (ctrl+r to expand)
⏺ Update Todos
⎿ ☒ Find and identify the markdown rendering library being used
☐ Analyze current CSS styling for markdown elements
☐ Adjust spacing for headings, lists, and line height
⏺ Now let me check the Tailwind typography configuration and look for any custom CSS:
⏺ Search(pattern: "**/*.css")
⎿ Found 3 files (ctrl+r to expand)
⏺ Search(pattern: "tailwind.config.*")
⎿ Found 1 file (ctrl+r to expand)
⏺ Search(pattern: "prose", include: "*.{js,jsx,ts,tsx,css}")
⎿ Found 2 files (ctrl+r to expand)
⏺ Read(tailwind.config.js)
⎿ Read 20 lines (ctrl+r to expand)
⏺ Read(src/index.css)
⎿ Read 32 lines (ctrl+r to expand)
⏺ Read(src/styles/github.css)
⎿ Read 120 lines (ctrl+r to expand)
⏺ Update Todos
⎿ ☒ Find and identify the markdown rendering library being used
☒ Analyze current CSS styling for markdown elements
☐ Adjust spacing for headings, lists, and line height
⏺ Perfect! I found the issue. You're using react-markdown with @tailwindcss/typography plugin (the prose classes). The spacing is controlled by Tailwind's typography plugin. Let me add custom CSS
overrides to tighten the spacing:
⏺ Update(tailwind.config.js)
⎿ Updated tailwind.config.js with 45 additions
11 border: '0',
12 backgroundColor: 'transparent',
13 },
14 + lineHeight: '1.5',
15 + h1: {
16 + marginTop: '1rem',
17 + marginBottom: '0.5rem',
18 + },
19 + h2: {
20 + marginTop: '1rem',
21 + marginBottom: '0.5rem',
22 + },
23 + h3: {
24 + marginTop: '0.75rem',
25 + marginBottom: '0.5rem',
26 + },
27 + h4: {
28 + marginTop: '0.75rem',
29 + marginBottom: '0.5rem',
30 + },
31 + h5: {
32 + marginTop: '0.75rem',
33 + marginBottom: '0.5rem',
34 + },
35 + h6: {
36 + marginTop: '0.75rem',
37 + marginBottom: '0.5rem',
38 + },
39 + p: {
40 + marginTop: '0.5rem',
41 + marginBottom: '0.5rem',
42 + },
43 + ul: {
44 + marginTop: '0.5rem',
45 + marginBottom: '0.5rem',
46 + },
47 + ol: {
48 + marginTop: '0.5rem',
49 + marginBottom: '0.5rem',
50 + },
51 + li: {
52 + marginTop: '0.25rem',
53 + marginBottom: '0.25rem',
54 + },
55 + blockquote: {
56 + marginTop: '0.5rem',
57 + marginBottom: '0.5rem',
58 + },
59 },
60 },
61 },
⏺ Update Todos
⎿ ☒ Find and identify the markdown rendering library being used
☒ Analyze current CSS styling for markdown elements
☒ Adjust spacing for headings, lists, and line height
⏺ Fixed! You're using react-markdown with Tailwind's @tailwindcss/typography plugin. I've updated tailwind.config.js:14-58 to tighten the spacing by:
- Reducing line height from default 1.75 to 1.5
- Cutting heading margins (top: 1rem, bottom: 0.5rem for h1/h2, smaller for h3-h6)
- Reducing paragraph and list margins to 0.5rem
- Shrinking list item margins to 0.25rem
The changes will take effect after restarting your dev server.
Total cost: $0.1342
Total duration (API): 1m 7.4s
Total duration (wall): 5m 14.3s
Total code changes: 45 lines added, 0 lines removed
Token usage by model:
claude-3-5-haiku: 638 input, 24 output, 0 cache read, 0 cache write
claude-sonnet: 227 input, 2.5k output, 166.5k cache read, 12.1k cache write
|
||
| .github/workflows | ||
| examples | ||
| src | ||
| .gitignore | ||
| .prettierignore | ||
| .prettierrc | ||
| AGENT.md | ||
| LICENSE | ||
| oranda.json | ||
| package.json | ||
| pnpm-lock.yaml | ||
| README.md | ||
| tsconfig.json | ||
| wrangler.jsonc | ||
🦑 use-mcp 🦑
A lightweight React hook for connecting to Model Context Protocol (MCP) servers. Simplifies authentication and tool calling for AI systems implementing the MCP standard.
Try it out: MCP Inspector | Cloudflare Workers AI Playground
Installation
npm install use-mcp
# or
pnpm add use-mcp
# or
yarn add use-mcp
Features
- 🔄 Automatic connection management with reconnection and retries
- 🔐 OAuth authentication flow handling with popup and fallback support
- 📦 Simple React hook interface for MCP integration
- 🧰 TypeScript types for editor assistance and type checking
- 📝 Comprehensive logging for debugging
- 🌐 Works with both HTTP and SSE (Server-Sent Events) transports
Quick Start
import { useMcp } from 'use-mcp/react'
function MyAIComponent() {
const {
state, // Connection state: 'discovering' | 'authenticating' | 'connecting' | 'loading' | 'ready' | 'failed'
tools, // Available tools from MCP server
error, // Error message if connection failed
callTool, // Function to call tools on the MCP server
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>
</div>
)
}
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 '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 'use-mcp'
export default function OAuthCallbackPage() {
useEffect(() => {
onMcpAuthorization()
}, [])
return (
<div>
<h1>Authenticating...</h1>
<p>This window should close automatically.</p>
</div>
)
}
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) |
Return Value
| Property | Type | Description |
|---|---|---|
state |
string |
Current connection state: 'discovering', 'authenticating', 'connecting', 'loading', 'ready', 'failed' |
tools |
Tool[] |
Available tools 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 |
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