Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions mcpjam-inspector/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion mcpjam-inspector/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@
"@hono/node-server": "^1.13.7",
"@hookform/resolvers": "^3.10.0",
"@mcp-ui/client": "^5.9.0",
"@mcpjam/sdk": "^0.8.4",
"@mcpjam/sdk": "^0.8.5",
"@modelcontextprotocol/ext-apps": "^1.0.1",
"@modelcontextprotocol/sdk": "^1.26.0",
"@ngrok/ngrok": "^1.6.0",
Expand Down
24 changes: 24 additions & 0 deletions mcpjam-web/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
dist
dist-ssr
*.local

# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
35 changes: 35 additions & 0 deletions mcpjam-web/MCPJAM_WEBAPP_GOAL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Objective

We want to build a lightweight web app version of MCPJam, no Hono server, full client app. Because it's going to be hosted, we can only connect to remote Streamable HTTP MCP servers. That means no STDIO or localhost enabled. This project must be very barebones and minimalist.

# Features
We will only have the server connections page and the LLM playground page.

1. Server connections page to manage server connections.
2. Be able to also connect to MCP servers that have Dynamic Client Registration
3. LLM playground to chat with the MCP server with different models
4. Same UI theme as the MCPJam inspector.

Eventually the LLM playground should have full parity to handle ChatGPT apps rendering and MCP apps rendering. For now, we can start off with basic MCP server chatting.

# Suggested instructions
- Create a global hook that manages the MCP connections. Use the `MCPClientManager` class from @mcpjam/sdk
- Have this hook expose some functions such as connect / disconnect MCP servers.
- Use Vercel AI-SDK to manage text streaming.

## Instructions for AI: Feel free to write more planning below here.


## Personal note on CORS pre-flight
Web app path (fails): browser uses @mcpjam/sdk/browser directly in McpConnectionsProvider.tsx (line 1) and calls manager.connectToServer(...) at McpConnectionsProvider.tsx (line 246).
Inspector path (works): browser posts config to local API (/api/mcp/connect) at mcp-api.ts (line 37), then backend calls mcpClientManager.connectToServer(...) at connect.ts (line 71), with manager created on the Node server in app.ts (line 86).
Why that matters:

Browser direct calls hit CORS/preflight rules.
For https://excalidraw-mcp-app.vercel.app/mcp, OPTIONS returns 405, so streamable fetch fails in browser (Failed to fetch).
Then SDK fallback tries SSE GET, and that endpoint returns 405, producing your SSE error.
Node backend (inspector) is not blocked by browser CORS preflight, so it can do the valid streamable POST and connect.
Extra proof from inspector design:

It also exposes its own bridge endpoints with explicit OPTIONS 204 for browser clients in http-adapters.ts (line 21).
So the behavior difference is expected: direct browser transport vs backend-proxied transport.
73 changes: 73 additions & 0 deletions mcpjam-web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
# React + TypeScript + Vite

This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.

Currently, two official plugins are available:

- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh

## React Compiler

The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation).

## Expanding the ESLint configuration

If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:

```js
export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...

// Remove tseslint.configs.recommended and replace with this
tseslint.configs.recommendedTypeChecked,
// Alternatively, use this for stricter rules
tseslint.configs.strictTypeChecked,
// Optionally, add this for stylistic rules
tseslint.configs.stylisticTypeChecked,

// Other configs...
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```

You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:

```js
// eslint.config.js
import reactX from 'eslint-plugin-react-x'
import reactDom from 'eslint-plugin-react-dom'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
// Other configs...
// Enable lint rules for React
reactX.configs['recommended-typescript'],
// Enable lint rules for React DOM
reactDom.configs.recommended,
],
languageOptions: {
parserOptions: {
project: ['./tsconfig.node.json', './tsconfig.app.json'],
tsconfigRootDir: import.meta.dirname,
},
// other options...
},
},
])
```
23 changes: 23 additions & 0 deletions mcpjam-web/eslint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import js from '@eslint/js'
import globals from 'globals'
import reactHooks from 'eslint-plugin-react-hooks'
import reactRefresh from 'eslint-plugin-react-refresh'
import tseslint from 'typescript-eslint'
import { defineConfig, globalIgnores } from 'eslint/config'

export default defineConfig([
globalIgnores(['dist']),
{
files: ['**/*.{ts,tsx}'],
extends: [
js.configs.recommended,
tseslint.configs.recommended,
reactHooks.configs.flat.recommended,
reactRefresh.configs.vite,
],
languageOptions: {
ecmaVersion: 2020,
globals: globals.browser,
},
},
])
13 changes: 13 additions & 0 deletions mcpjam-web/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>mcpjam-web</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
Loading