Skip to content
This repository was archived by the owner on May 21, 2026. It is now read-only.

Commit 2f62e6b

Browse files
committed
feat: Implement MCP Client and Connector Architecture
- Added MCPClient class for managing server configurations and sessions. - Introduced configuration loading and connector creation functions. - Created base connector class and specific implementations for HTTP, STDIO, and WebSocket connections. - Developed session management with MCPSession class for handling tool calls and resource management. - Implemented connection managers for different transport types (SSE, STDIO, WebSocket). - Added logging functionality for better debugging and error tracking. - Configured TypeScript settings for the project.
0 parents  commit 2f62e6b

34 files changed

Lines changed: 7763 additions & 0 deletions
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
name: Create GitHub Release
2+
3+
on:
4+
push:
5+
tags:
6+
- 'v*'
7+
8+
jobs:
9+
build-and-release:
10+
runs-on: ubuntu-latest
11+
permissions:
12+
contents: write
13+
steps:
14+
- name: Checkout code
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-depth: 0
18+
19+
- name: Setup Node.js
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: '22'
23+
24+
- name: Install dependencies
25+
run: npm ci
26+
27+
- name: Build
28+
run: npm run build
29+
30+
- name: Get package version
31+
id: package-version
32+
run: echo "VERSION=$(node -p "require('./package.json').version")" >> $GITHUB_OUTPUT
33+
34+
- name: Generate changelog
35+
id: changelog
36+
run: |
37+
PREVIOUS_TAG=$(git describe --tags --abbrev=0 HEAD^ 2>/dev/null || echo "")
38+
if [ -z "$PREVIOUS_TAG" ]; then
39+
CHANGELOG=$(git log --pretty=format:"* %s (%h)" $(git rev-list --max-parents=0 HEAD)..HEAD)
40+
else
41+
CHANGELOG=$(git log --pretty=format:"* %s (%h)" $PREVIOUS_TAG..HEAD)
42+
fi
43+
echo "CHANGELOG<<EOF" >> $GITHUB_OUTPUT
44+
echo "$CHANGELOG" >> $GITHUB_OUTPUT
45+
echo "EOF" >> $GITHUB_OUTPUT
46+
47+
- name: Create Release
48+
uses: softprops/action-gh-release@v1
49+
with:
50+
tag_name: v${{ steps.package-version.outputs.VERSION }}
51+
name: Release v${{ steps.package-version.outputs.VERSION }}
52+
body: |
53+
## Changelog
54+
${{ steps.changelog.outputs.CHANGELOG }}
55+
draft: false
56+
prerelease: false
57+
env:
58+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

.github/workflows/release-npm.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Publish to NPM
2+
3+
on:
4+
release:
5+
types: [created]
6+
7+
jobs:
8+
build-and-publish:
9+
runs-on: ubuntu-latest
10+
steps:
11+
- name: Checkout code
12+
uses: actions/checkout@v4
13+
14+
- name: Setup Node.js
15+
uses: actions/setup-node@v4
16+
with:
17+
node-version: '22'
18+
registry-url: 'https://registry.npmjs.org/'
19+
20+
- name: Install dependencies
21+
run: npm ci
22+
23+
- name: Build
24+
run: npm run build
25+
26+
- name: Publish to NPM
27+
run: npm publish
28+
env:
29+
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}

.gitignore

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2+
3+
# Dependencies
4+
node_modules
5+
.pnp
6+
.pnp.js
7+
8+
# Local env files
9+
.env
10+
.env.local
11+
.env.development.local
12+
.env.test.local
13+
.env.production.local
14+
15+
# Testing
16+
coverage
17+
18+
# Turbo
19+
.turbo
20+
21+
# Vercel
22+
.vercel
23+
24+
# Build Outputs
25+
.next/
26+
out/
27+
build
28+
dist
29+
30+
31+
# Debug
32+
npm-debug.log*
33+
yarn-debug.log*
34+
yarn-error.log*
35+
36+
# Misc
37+
.DS_Store
38+
*.pem
39+
40+
41+
# Python-generated files
42+
__pycache__/
43+
*.py[oc]
44+
build/
45+
dist/
46+
wheels/
47+
*.egg-info
48+
.coverage
49+
agent_history.gif
50+
static/browser_history/*.gif
51+
52+
# Virtual environments
53+
.venv
54+
55+
# user conf
56+
conf.yaml

.vscode/settings.json

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
{
2+
// Disable the default formatter, use eslint instead
3+
"prettier.enable": false,
4+
"editor.formatOnSave": false,
5+
6+
// Auto fix
7+
"editor.codeActionsOnSave": {
8+
"source.fixAll.eslint": "explicit",
9+
"source.organizeImports": "never"
10+
},
11+
12+
// Silent the stylistic rules in you IDE, but still auto fix them
13+
"eslint.rules.customizations": [
14+
{ "rule": "style/*", "severity": "off", "fixable": true },
15+
{ "rule": "format/*", "severity": "off", "fixable": true },
16+
{ "rule": "*-indent", "severity": "off", "fixable": true },
17+
{ "rule": "*-spacing", "severity": "off", "fixable": true },
18+
{ "rule": "*-spaces", "severity": "off", "fixable": true },
19+
{ "rule": "*-order", "severity": "off", "fixable": true },
20+
{ "rule": "*-dangle", "severity": "off", "fixable": true },
21+
{ "rule": "*-newline", "severity": "off", "fixable": true },
22+
{ "rule": "*quotes", "severity": "off", "fixable": true },
23+
{ "rule": "*semi", "severity": "off", "fixable": true }
24+
],
25+
26+
// Enable eslint for all supported languages
27+
"eslint.validate": [
28+
"javascript",
29+
"javascriptreact",
30+
"typescript",
31+
"typescriptreact",
32+
"vue",
33+
"html",
34+
"markdown",
35+
"json",
36+
"json5",
37+
"jsonc",
38+
"yaml",
39+
"toml",
40+
"xml",
41+
"gql",
42+
"graphql",
43+
"astro",
44+
"svelte",
45+
"css",
46+
"less",
47+
"scss",
48+
"pcss",
49+
"postcss"
50+
]
51+
}

LICENSE

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2025 zane
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

README.md

Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
<h1 align="center">Unified MCP Client Library</h1>
2+
3+
[![](https://img.shields.io/npm/dw/@modelcontextprotocol/mcp-client.svg)](https://www.npmjs.com/package/@modelcontextprotocol/mcp-client)
4+
[![npm version](https://img.shields.io/npm/v/@modelcontextprotocol/mcp-client.svg)](https://www.npmjs.com/package/@modelcontextprotocol/mcp-client)
5+
[![License](https://img.shields.io/github/license/zandko/mcp-use)](https://github.com/zandko/mcp-use/blob/main/LICENSE)
6+
[![Code style: ESLint](https://img.shields.io/badge/code%20style-eslint-4B32C3.svg)](https://eslint.org)
7+
[![GitHub stars](https://img.shields.io/github/stars/zandko/mcp-use?style=social)](https://github.com/zandko/mcp-use/stargazers)
8+
9+
🌐 **MCP Client** is the open-source way to connect **any LLM to any MCP server** in TypeScript/Node.js, letting you build custom agents with tool access without closed-source dependencies.
10+
11+
💡 Let developers easily connect any LLM via LangChain.js to tools like web browsing, file operations, 3D modeling, and more.
12+
13+
---
14+
15+
## ✨ Key Features
16+
17+
| Feature | Description |
18+
| ------------------------------- | -------------------------------------------------------------------------- |
19+
| 🔄 **Ease of use** | Create an MCP-capable agent in just a few lines of TypeScript. |
20+
| 🤖 **LLM Flexibility** | Works with any LangChain.js-supported LLM that supports tool calling. |
21+
| 🌐 **HTTP Support** | Direct SSE/HTTP connection to MCP servers. |
22+
| ⚙️ **Dynamic Server Selection** | Agents select the right MCP server from a pool on the fly. |
23+
| 🧩 **Multi-Server Support** | Use multiple MCP servers in one agent. |
24+
| 🛡️ **Tool Restrictions** | Restrict unsafe tools like filesystem or network. |
25+
| 🔧 **Custom Agents** | Build your own agents with LangChain.js adapter or implement new adapters. |
26+
27+
---
28+
29+
## 🚀 Quick Start
30+
31+
### Installation
32+
33+
```bash
34+
# Install from npm
35+
npm install mcp-use
36+
# LangChain.js and your LLM provider (e.g., OpenAI)
37+
npm install langchain @langchain/openai dotenv
38+
```
39+
40+
Create a `.env`:
41+
42+
```ini
43+
OPENAI_API_KEY=your_api_key
44+
```
45+
46+
### Basic Usage
47+
48+
```ts
49+
import { ChatOpenAI } from '@langchain/openai'
50+
import { MCPAgent, MCPClient } from 'mcp-use'
51+
import 'dotenv/config'
52+
53+
async function main() {
54+
// 1. Configure MCP servers
55+
const config = {
56+
mcpServers: {
57+
playwright: { command: 'npx', args: ['@playwright/mcp@latest'] }
58+
}
59+
}
60+
const client = MCPClient.fromDict(config)
61+
62+
// 2. Create LLM
63+
const llm = new ChatOpenAI({ modelName: 'gpt-4o' })
64+
65+
// 3. Instantiate agent
66+
const agent = new MCPAgent({ llm, client, maxSteps: 20 })
67+
68+
// 4. Run query
69+
const result = await agent.run('Find the best restaurant in Tokyo using Google Search')
70+
console.log('Result:', result)
71+
}
72+
73+
main().catch(console.error)
74+
```
75+
76+
---
77+
78+
## 📂 Configuration File
79+
80+
You can store servers in a JSON file:
81+
82+
```json
83+
{
84+
"mcpServers": {
85+
"playwright": {
86+
"command": "npx",
87+
"args": ["@playwright/mcp@latest"]
88+
}
89+
}
90+
}
91+
```
92+
93+
Load it:
94+
95+
```ts
96+
import { MCPClient } from 'mcp-use'
97+
const client = MCPClient.fromConfigFile('./mcp-config.json')
98+
```
99+
100+
---
101+
102+
## 🔄 Multi-Server Example
103+
104+
```ts
105+
const config = {
106+
mcpServers: {
107+
airbnb: { command: 'npx', args: ['@openbnb/mcp-server-airbnb'] },
108+
playwright: { command: 'npx', args: ['@playwright/mcp@latest'] }
109+
}
110+
}
111+
const client = MCPClient.fromDict(config)
112+
const agent = new MCPAgent({ llm, client, useServerManager: true })
113+
await agent.run('Search Airbnb in Barcelona, then Google restaurants nearby')
114+
```
115+
116+
---
117+
118+
## 🔒 Tool Access Control
119+
120+
```ts
121+
const agent = new MCPAgent({
122+
llm,
123+
client,
124+
disallowedTools: ['file_system', 'network']
125+
})
126+
```
127+
128+
## 📜 License
129+
130+
MIT © [Zane](https://github.com/zandko)

eslint.config.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import antfu from '@antfu/eslint-config'
2+
3+
export default antfu({
4+
formatters: true,
5+
typescript: true,
6+
})

index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { MCPAgent } from './src/agents/mcp_agent.js'
2+
import { MCPClient } from './src/client.js'
3+
import { loadConfigFile } from './src/config.js'
4+
import { BaseConnector } from './src/connectors/base.js'
5+
import { HttpConnector } from './src/connectors/http.js'
6+
import { StdioConnector } from './src/connectors/stdio.js'
7+
import { WebSocketConnector } from './src/connectors/websocket.js'
8+
9+
import { Logger, logger } from './src/logging.js'
10+
import { MCPSession } from './src/session.js'
11+
12+
export { BaseConnector, HttpConnector, loadConfigFile, Logger, logger, MCPAgent, MCPClient, MCPSession, StdioConnector, WebSocketConnector }

0 commit comments

Comments
 (0)