A Model Context Protocol (MCP) server that enables ChatGPT integration with Index Network's discovery protocol.
This repository demonstrates Index Network's MCP server implementation, showcasing how to integrate with ChatGPT using React widgets and following best practices for MCP development.
- Features
- Quick Start
- Usage
- Security
- How It Works
- Adding New Widgets
- Widget Hooks
- Performance
- Troubleshooting
- Contributing
- Support
- License
- References
- 🔥 Hot Reload - Edit widgets and see changes instantly in development
- ⚡ Modern Tooling - Vite + React for fast builds and optimal performance
- 🎨 Custom Hooks -
useWidgetProps
,useOpenAiGlobal
,useWidgetState
for seamless ChatGPT integration - 🛠️ MCP Inspector - Test and debug widgets without ChatGPT integration
- 📦 TypeScript 5.7.2 - Fully typed codebase for better development experience
- 🚀 Development Ready - Optimized builds with hashed assets and proper MCP protocol implementation
- 📝 Clean Code - Follows TypeScript commenting best practices with JSDoc documentation
- Node.js: 22.12.0 or higher
- Operating System: macOS, Linux, or Windows (with WSL2 recommended)
- Memory: Minimum 2GB RAM (4GB recommended for development)
- Port: 3002 available (configurable via
MCP_SERVER_PORT
) - Network: Internet access for npm packages and ngrok tunneling
npm install
cd widgets && npm install && cd ..
# Configure environment
cp env.example .env
# Edit .env with your ngrok authtoken (optional)
npm run dev
This starts Vite in watch mode and the MCP server with auto-restart. Edit widgets/src/echo/echo.css
→ save → see changes in ~2 seconds.
npm test # Launches MCP Inspector
Variable | Description | Default |
---|---|---|
MCP_SERVER_PORT |
Server port | 3002 |
NGROK_AUTHTOKEN |
ngrok auth token | Required |
NODE_ENV |
Environment | development |
Get ngrok authtoken: Sign up at ngrok.com, then run ngrok config add-authtoken YOUR_TOKEN
- Build:
npm run build
- Start:
npm start
- Expose:
ngrok http 3002
(or setNGROK_AUTHTOKEN
in.env
) - Configure ChatGPT with:
https://your-url.ngrok-free.app/mcp
Use the echo tool to display "Hello, World!"
// widgets/src/my-widget/MyWidget.tsx
import { useWidgetProps } from '../use-widget-props';
import { useOpenAiGlobal } from '../use-openai-global';
interface MyWidgetProps {
title: string;
data: any[];
}
export function MyWidget() {
const props = useWidgetProps<MyWidgetProps>({
title: '',
data: []
});
const theme = useOpenAiGlobal('theme');
return (
<div className={`widget ${theme}`}>
<h3>{props.title}</h3>
<ul>
{props.data.map((item, index) => (
<li key={index}>{item.name}</li>
))}
</ul>
</div>
);
}
# Development
NODE_ENV=development npm run dev
# Production with custom port
MCP_SERVER_PORT=8080 NODE_ENV=production npm start
# With ngrok authtoken
NGROK_AUTHTOKEN=your_token npm run dev
Regularly audit your dependencies for known vulnerabilities:
# Check for vulnerabilities
npm audit
# Fix automatically (use with caution)
npm audit fix
# Check for outdated packages
npm outdated
- Environment Variables: Never commit sensitive data to version control
- CORS Configuration: The server uses permissive CORS (
origin: '*'
) for development - restrict in production - ngrok Tunnels: Use authenticated ngrok sessions for production deployments
- Dependencies: Keep all dependencies up to date and audit regularly
- HTTPS: Always use HTTPS in production environments
- Set
NODE_ENV=development
- Use ngrok for secure tunneling
- Run
npm audit
and fix vulnerabilities - Keep dependencies up to date
- Use environment variables for sensitive data
- Review CORS configuration for production readiness
src/server.ts # MCP server with tool registration
widgets/src/ # React widgets with hooks
widgets/dist/ # Built assets (hashed filenames)
File change → Vite rebuild → Nodemon restart → Updated widget
Key files:
nodemon.json
- File watching configwidgets/vite.config.ts
- Build configpackage.json
- Scripts and dependencies
mkdir widgets/src/my-widget
Create:
MyWidget.tsx
- React componentmy-widget.css
- Stylesindex.tsx
- Entry pointindex.html
- Template with<div id="my-widget-root">
Add entry in widgets/vite.config.ts
:
input: {
echo: './src/echo/index.html',
myWidget: './src/my-widget/index.html'
}
In src/server.ts
:
const myWidgetHtml = readFileSync(
join(__dirname, '../widgets/dist/src/my-widget/index.html'),
'utf-8'
);
server.registerTool("my-tool", {
title: "My Tool",
description: "Tool description",
inputSchema: z.object({ data: z.string() })
}, async (params) => ({
content: [{ type: "text", text: "Result" }],
structuredContent: params,
_meta: {
"openai/widgetAccessible": true,
"openai.com/widget": {
type: "resource",
resource: {
uri: "ui://widget/my-widget.html",
mimeType: "text/html+skybridge",
text: myWidgetHtml
}
}
}
}));
import { useWidgetProps } from '../use-widget-props';
import { useOpenAiGlobal } from '../use-openai-global';
import { useWidgetState } from '../use-widget-state';
function MyWidget() {
const props = useWidgetProps<{ message: string }>();
const theme = useOpenAiGlobal('theme');
const [state, setState] = useWidgetState({ count: 0 });
return <div>{props.message}</div>;
}
- Hot Reload: Development changes are reflected in ~2 seconds
- Build Optimization: Vite provides fast builds with hashed assets for cache busting
- Memory Usage: Monitor memory consumption during development with
node --trace-sync-io
- Bundle Size: Widgets are built as separate chunks for optimal loading
# Monitor synchronous I/O operations
node --trace-sync-io dist/server.js
# Check memory usage
node --inspect dist/server.js
- Static Assets: Widget assets are served with proper cache headers
- Hot Reload: Fast development iteration with Vite
- Build Optimization: Hashed assets for cache busting
- Logging: Console logging for development debugging
Port 3002 already in use?
# Kill process using port 3002
lsof -ti:3002 | xargs kill -9
# Or use a different port
MCP_SERVER_PORT=3003 npm run dev
Hot reload not working?
- Check terminal for
[nodemon] restarting due to changes...
- Ensure Vite is running:
cd widgets && npm run dev
- Clear build cache:
rm -rf widgets/dist && npm run build
Widget not displaying in ChatGPT?
- Verify ngrok tunnel is active:
ngrok http 3002
- Check MCP endpoint is accessible:
curl https://your-url.ngrok-free.app/mcp
- Ensure widget HTML is built:
npm run build
TypeScript errors?
- Run type check:
npm run type-check
- Clear TypeScript cache:
rm -rf node_modules/.cache
- Reinstall dependencies:
rm -rf node_modules && npm install
Environment variables not loading?
- Ensure
.env
file exists:cp env.example .env
- Check variable names match exactly (case-sensitive)
- Restart the development server after changes
We welcome contributions to improve Index Network's MCP server! Here's how to get started:
- Fork the repository
- Clone your fork:
git clone https://github.com/your-username/index-network-mcp.git
- Install dependencies:
npm install && cd widgets && npm install && cd ..
- Create a feature branch:
git checkout -b feature/your-feature-name
- Make your changes following our coding standards
- Submit a pull request with a clear description
- Use TypeScript for all new code
- Follow existing code style and patterns
- Add tests for new functionality
- Update documentation as needed
- Ensure all linting passes:
npm run lint
This project follows clean code commenting principles:
- JSDoc for Public APIs: All exported functions, classes, and types use JSDoc with
@param
,@returns
, and@example
tags - Self-Explanatory Code: Prefer clear variable names and small functions over explanatory comments
- Minimal Inline Comments: Only use
//
comments for non-obvious business logic or architectural decisions - No Redundant Comments: Avoid stating the obvious or repeating what the code already shows
- Maintainable Documentation: Keep comments in sync with code changes
Examples of good commenting practices can be found in:
widgets/src/use-widget-props.ts
- Comprehensive JSDoc with exampleswidgets/src/use-widget-state.ts
- Real-world usage examplessrc/server.ts
- JSDoc for exported items and route handlers
Found a bug or have a feature request? Please:
- Check existing issues first
- Create a new issue with clear steps to reproduce
- Include environment details (Node.js 22.12.0+, OS, etc.)
Need help? Here are your options:
- Documentation: Check this README and the References section
- Issues: Report bugs or request features via GitHub Issues
- Community: Join the Index Network community at index.network
- Email: Contact us at hello@index.network
MIT - See LICENSE
- Index Network - Discovery protocol for web3
- ngrok - Secure tunneling to localhost
- OpenAI Apps SDK - Framework for building ChatGPT apps
- OpenAI Apps SDK Examples - Example implementations
- Model Context Protocol TypeScript SDK - Official MCP SDK
- MCP Inspector - Visual testing tool for MCP servers