Skip to content
Open
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
41a20bc
feat: first implementation of mcp building based on npm pkgs
FedericoAmura Jul 2, 2025
9cda182
feat: first implementation of mcp building based on npm pkgs - mcp sd…
FedericoAmura Jul 2, 2025
b24254d
feat: servers graceful shutdown, json and registry definitions consol…
FedericoAmura Jul 3, 2025
4774cea
feat: deleted app or tool checks and not prod notification
FedericoAmura Jul 4, 2025
3e8d8cf
fix: remove unused pkgs in mcp-sdk
FedericoAmura Jul 4, 2025
10a1052
feat: use pnpm locally for tools pkg install but npm for out-in-the-w…
FedericoAmura Jul 4, 2025
4ccb43a
feat: comment on require vs import
FedericoAmura Jul 4, 2025
b6f7368
Merge branch 'refs/heads/main' into feature/drel-817-migrate-mcp-from…
FedericoAmura Jul 4, 2025
c1e3897
fix: remove old version plan
FedericoAmura Jul 4, 2025
8c16a12
feat: move tool pkgs installation to server start and away from first…
FedericoAmura Jul 4, 2025
a6d838a
fix: incorrect bundled vincent tool destructuring
FedericoAmura Jul 4, 2025
2480c2c
fix: move which types dev dependency
FedericoAmura Jul 4, 2025
72221c4
chore: code documentation
FedericoAmura Jul 4, 2025
5ce2a6d
chore: doc and readme updates
FedericoAmura Jul 4, 2025
1f620fd
chore: add release plan
FedericoAmura Jul 4, 2025
74da7c6
feat: add descriptions exposed by tools
FedericoAmura Jul 7, 2025
e168934
Merge branch 'main' into feature/drel-817-migrate-mcp-from-ipfc-cids-…
FedericoAmura Jul 9, 2025
b374d76
Merge branch 'main' into feature/drel-817-migrate-mcp-from-ipfc-cids-…
FedericoAmura Jul 9, 2025
2ec989c
fix: use once to call graceful shutdown function
FedericoAmura Jul 9, 2025
de34b8c
feat: convert parameters array in app def json into an object
FedericoAmura Jul 9, 2025
1b1ea11
Merge branch 'refs/heads/main' into feature/drel-817-migrate-mcp-from…
FedericoAmura Jul 10, 2025
6102180
feat: migrate from npm and pnpm to npx-import
FedericoAmura Jul 10, 2025
5e70421
fix: move tools sdk as prod dep in mcp server
FedericoAmura Jul 10, 2025
3a56bcb
Merge branch 'refs/heads/main' into feature/drel-817-migrate-mcp-from…
FedericoAmura Jul 10, 2025
bd08339
feat: use registry sdk and allow for version input as env variable
FedericoAmura Jul 10, 2025
5bcd28f
feat: require mcp-sdk receives vincent bundled tools in its app defin…
FedericoAmura Jul 11, 2025
577ecdb
feat: move tools sdk in mcp sdk to dev dep
FedericoAmura Jul 11, 2025
4e84739
chore: update docs
FedericoAmura Jul 11, 2025
a5680f6
chore: comments updates
FedericoAmura Jul 11, 2025
eccf6ed
fix: set exitCode instead of forcefully exiting
FedericoAmura Jul 11, 2025
5303ce0
feat: just warn and skip on registry deleted tools
FedericoAmura Jul 11, 2025
b298aeb
feat: app version enabled check
FedericoAmura Jul 11, 2025
1a6d82f
feat: app tool in json file exists in registry
FedericoAmura Jul 11, 2025
c49d29f
feat: harden tool failure check
FedericoAmura Jul 11, 2025
bc57d89
fix: make tool params describe override non-mutative on the vincent tool
FedericoAmura Jul 11, 2025
02d8822
fix: removed tools sdk from the wrong package json file
FedericoAmura Jul 11, 2025
99e2d6d
feat: separate env verifications for stdio and http execution making …
FedericoAmura Jul 13, 2025
a9040ab
feat: migrate nonce and transport managers to node-cache
FedericoAmura Jul 13, 2025
58d1109
Merge branch 'main' into feature/drel-817-migrate-mcp-from-ipfc-cids-…
FedericoAmura Jul 13, 2025
5033694
chore: update lockfile
FedericoAmura Jul 13, 2025
51f1340
feat: migrate to the registerTool syntax and add getters also as reso…
FedericoAmura Jul 14, 2025
70d6bac
feat: close transport and nonce managers on http server cleanup
FedericoAmura Jul 14, 2025
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
7 changes: 0 additions & 7 deletions .nx/version-plans/version-plan-1750681850131.md

This file was deleted.

7 changes: 7 additions & 0 deletions .nx/version-plans/version-plan-1751658342657.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
app-sdk: minor
mcp-sdk: major
mcp: major
---

Migration of MCP building from JSON file exclusively to Registry based with json available for overrides
15 changes: 7 additions & 8 deletions docs/src/Developers/App-Agent-Developers/MCP.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ title: MCP - Model Context Protocol

Any Vincent App can be converted into a Model Protocol Server (MCP) that can be consumed by any Large Language Model (LLM) with support for the MCP standard.

We provide an [implementation of an MCP Server](https://github.com/LIT-Protocol/Vincent/tree/feature/main/packages/apps/mcp), connectable through STDIO and HTTP transports. You can use it (forking or [using `npx`](https://www.npmjs.com/package/@lit-protocol/vincent-mcp-server)) with your keys and Vincent Apps or you can customize the whole process to make your own Vincent MCP Server.
We provide an [implementation of an MCP Server](https://github.com/LIT-Protocol/Vincent/tree/feature/main/packages/apps/mcp), connectable through STDIO and HTTP transports. You can use it (forking or [using `npx`](https://www.npmjs.com/package/@lit-protocol/vincent-mcp-server)) with your keys and Vincent Apps or you can customize the whole process to make your own Vincent MCP Server based on our [MCP SDK](https://github.com/LIT-Protocol/Vincent/blob/main/packages/libs/mcp-sdk/README.md).

By following this process, your Vincent App tools will be exposed to LLMs as a set of MCP tools. The MCP server can also be extended with custom tools and prompts to suit your specific needs.
By following this process, your Vincent App tools will be exposed to LLMs as a set of MCP tools. The MCP server can also be extended with custom tools and prompts to suit your specific needs or provide extra capabilities around the Vincent Tool ecosystem.

And if you're building an AI application, check out our [OpenAI AgentKit demo](https://github.com/LIT-Protocol/Vincent-MCP-OpenAI-AgentKit) for a guide on how to integrate your Vincent App with the OpenAI AgentKit.

Expand All @@ -34,7 +34,8 @@ const appDef: VincentAppDef = {
name: 'My Vincent App',
description: 'A Vincent application that executes tools for its delegators',
tools: {
QmIpfsCid1: {
'@organization/npm-published-vincent-tool': {
version: '1.0.0',
name: 'myTool',
description: 'A tool that does something',
parameters: [
Expand All @@ -55,8 +56,6 @@ const appDef: VincentAppDef = {
const server = await getVincentAppServer(wallet, appDef);
```

You can check the [Uniswap Swap example app json](https://github.com/LIT-Protocol/Vincent/blob/feature/main/packages/apps/mcp/vincent-app.example.json) for a complete Vincent App definition.

## Extending the MCP Server

At this moment you can add more tools, resources or prompts to the server.
Expand All @@ -67,7 +66,7 @@ server.resource(...);
server.prompt(...);
```

These tools, resources and prompts will be exposed in the server along with the ones from the Vincent App definition. Consider adding any other tools that you want to be executed by the LLM and that are not Vincent Tools such as tools to query balance or fetch useful data from external sources.
These tools, resources and prompts will be exposed in the server along with the ones from the Vincent App definition. Consider adding any other tools that you want to be executed by the LLM and that are not Vincent Tools. For example, you could add tools to query balance or fetch useful data from external sources.

## Picking a Transport

Expand Down Expand Up @@ -126,7 +125,7 @@ This MCP Server includes:

- HTTP and STDIO transports
- `.env` file support for environment definition
- App definition with a custom JSON file to define which tools and params are exposed to LLMs
- App definition overriding with a custom JSON file to refine descriptions and filter tools to be exposed to LLMs
- Support for delegatee and delegators in HTTP transport
- Delegators MUST authenticate with SIWE OR their Vincent JWT
- Delegatees MUST identify with SIWE
Expand Down Expand Up @@ -162,7 +161,7 @@ Before deploying, you'll need to create the following two files in the root of y
CMD ["npx", "@lit-protocol/vincent-mcp-server", "http"]
```

2. Create the Vincent App JSON definition file. Fill it with the data of your Vincent: ID, version, name, description and tools data. Check the [Uniswap Swap example app json](https://github.com/LIT-Protocol/Vincent/blob/feature/main/packages/apps/mcp/vincent-app.example.json) for a complete Vincent App definition.
2. Create the Vincent App JSON definition override file. Fill it with the data of your Vincent App you want to override: ID, version, name, description and tools data. Check the [Uniswap Swap example app json](https://github.com/LIT-Protocol/Vincent/blob/feature/main/packages/apps/mcp/vincent-app.example.json) for a complete Vincent App override file.

3. Add both files to git. Commit and push them to your repository to use as source for Heroku or Render.

Expand Down
78 changes: 39 additions & 39 deletions packages/apps/mcp/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,49 +6,45 @@ It leverages the `@lit-protocol/vincent-mcp-sdk` to build a server from a Vincen

## Setup

- Copy `vincent-app.example.json` to `vincent-app.json` or any other name you want and configure your Vincent App definition in it.
- Copy `.env.example` to `.env` and fill in the values. Use absolute paths for the `VINCENT_APP_JSON_DEFINITION` value.
- Optional: Copy `vincent-app.example.json` to `vincent-app.json` or any other name you want and configure your Vincent App definition overrides in it. If no overrides are needed, then this file can be omitted.
- Optional: Copy `.env.example` to `.env` and fill in the values. Use absolute paths for the `VINCENT_APP_JSON_DEFINITION` value. You can also pass them via CLI arguments when calling the script.

# Writing App definition JSON file
# Writing App definition overrides in the JSON file

To define the Vincent App that will be transformed into an MCP Server, a JSON definition of it must be provided.
Name and descriptions provided by developers in the registry might not be very descriptive to LLMs or you may want to modify them.

In order to override any of those values, create a `.json` file with the following structure:

```json
{
"id": "8462368", // The Id of the Vincent App
"version": "1", // The version of the Vincent App
"name": "My Vincent App", // Name of the Vincent App. Can be overriden, doesn't have to be the same as in the registry.
"description": "A Vincent application that executes tools for its delegators", // Description of the Vincent App. Can be overriden, doesn't have to be the same as in the registry.
// Adding a tools object will override what is already present in the registry. Without this field, all tools from the registry will be exposed.
"tools": {
// Any tool that you want to expose to the LLM has to be included using its IPFS CID as key in this object. If a tool is not included, it is not exposed as an MCP Server tool.
"QmIpfsCid1": {
"name": "myTool", // Name of the tool. Can be overriden, doesn't have to be the same as in the registry.
"description": "A tool that does something", // Description of the tool. Can be overriden, doesn't have to be the same as in the registry.
// All parameters of the tool have to be added under this array or the LLM won't be able to see them or provide values for it
// Any tool that you want to expose to the LLM has to be included using its NPM package name as key in this object. If a tool is not included, it is not exposed as an MCP Server tool.
"vincent-tool-npm-pkg-name": {
"name": "myTool", // Name of the tool. Defaults to npm pkg name.
"description": "A tool that does something", // Description of the tool.
"parameters": [
{
"name": "param1", // Name of the param. Cannot be overriden.
"type": "string", // Type of the param. Must be the type the tool expects.
"description": "A parameter that is used in the tool to do something" // Description of the param. Can be overriden.
"name": "param1", // Name of the param. Used to identify and apply the rest of properties.
"description": "A parameter that is used in the tool to do something" // Description of the param.
}
// ...rest of params you want to expose.
// Any optional param that is not included here will be exposed by the tool.
// ...rest of params you want to override.
]
}
},
"vincent-tool-without-overrides": {} // Empty objects mean that the tool is exposed but with default values.
}
}
```

For any value that can be overriden, consider that those are the hints the LLM uses to know how to use the tool. Therefore, those are good places to provide any information you want the LLM to know about the tool such as units, formats, examples or pre-conditions to check.

If you are the owner of the app, most of the data can be obtained from the Vincent App page in the Vincent dashboard.
When the `tools` property is omitted, all tools from the registry will be exposed. So when overriding at least one tool, you need to specify all others that you want to still expose as MCP tools, even with empty values.

If you are not the owner of the app, the tool fields and its included tools IPFS CIDs are shown in the consent screen.

The IPFS CID can also be obtained from the bundled tool code published in npm. For example [vincent-tool-metadata.json](../tool-erc20-approval/src/generated/vincent-tool-metadata.json) for our ERC20 approval tool.
To get the tool params from source code, you can check the tool schemas such as [schemas.ts](../tool-erc20-approval/src/lib/schemas.ts) for our ERC20 approval tool.
For any value that can be overriden, consider that those are the hints the LLM uses to know how to use the tool. Therefore, those are good places to provide any information you want the LLM to know about the tool such as units, formats, examples or pre-conditions to check.

Any tool created using our [Tools and Policies SDK](https://www.npmjs.com/package/@lit-protocol/vincent-tool-sdk) will provide those files.
Tools included in definition MUST be published in NPM and imported using their package names. Also they must be part of the Vincent App and already registered. Any tool that is not part of that specific app will fail its invocation.

# Running

Expand All @@ -66,10 +62,13 @@ You can run the Vincent MCP server directly using npx without downloading the re
npx @lit-protocol/vincent-mcp-server stdio
```

When setting this in the LLM client, pass it the necessary environment variables from your client. These env variables include:
When setting this in the LLM client, pass it the necessary environment variables from your LLM client. These env variables include:

- `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App definition JSON file
- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are). This private key MUST be an allowed delegatee of the Vincent App defined in the JSON.
- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are). This private key MUST be an allowed delegatee of the Vincent App.
- (Optional) `VINCENT_APP_ID`: The Vincent App Id you want to run as an MCP Server
- (Optional) `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App overrides JSON file

Either in `VINCENT_APP_ID` or in the `VINCENT_APP_JSON_DEFINITION` file, the App Id MUST be specified. So one of those values is required.

### HTTP mode

Expand All @@ -79,28 +78,29 @@ npx @lit-protocol/vincent-mcp-server http

In HTTP mode, the environment variables are configured on the server itself, not the client running it.

These commands require the following environment variables to be set:
To configure runtime environment in this mode, set the following environment variables:

- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are). This private key MUST be an allowed delegatee of the Vincent App.
- (Optional) `VINCENT_APP_ID`: The Vincent App Id you want to run as an MCP Server
- (Optional) `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App overrides JSON file
- `EXPECTED_AUDIENCE`: The audience that you expect JWTs to have. Vincent populates this with the redirect URLs. Likely you want this server to be one of those URLs.
- `VINCENT_APP_JSON_DEFINITION`: Path to your Vincent App definition JSON file
- `VINCENT_DELEGATEE_PRIVATE_KEY`: The private key of the delegatee. This is the one you added in the Vincent App Dashboard as [an authorized signer for your app](https://docs.heyvincent.ai/documents/Quick_Start.html#:~:text=New%20App%22%20button.-,Delegatees,-%3A%20Delegatees%20are).
- `VINCENT_MCP_BASE_URL`: This MCP server URL
- `PORT` (for HTTP mode only): The port to run the HTTP server on (defaults to 3000)

Other optional environment variables include:
- `VINCENT_MCP_BASE_URL`: This MCP server URL. Used to generate SIWE messages and verify signatures
- `VINCENT_REGISTRY_URL`: This Vincent Registry server URL. Will be queried to get the Vincent App and its tools info
- (Optional) `PORT`: The port to run the HTTP server on (defaults to 3000)
- (Optional) `HTTP_TRANSPORT_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- (Optional) `HTTP_TRANSPORT_TTL`: Defines the time (milliseconds) that a transport will still be considered in use after the last time it was actually used. Defaults to 1 hour
- (Optional) `SIWE_EXPIRATION_TIME`: Duration of the generated SIWE message to sign. Defaults to 1 hour
- (Optional) `SIWE_NONCE_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- (Optional) `SIWE_NONCE_TTL`: Defines the time (milliseconds) that a SIWE nonce will still be considered valid after it was created. Defaults to 5 minutes

- `HTTP_TRANSPORT_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- `HTTP_TRANSPORT_TTL`: Defines the time (milliseconds) that a transport will still be considered in use after the last time it was actually used. Defaults to 1 hour
- `SIWE_EXPIRATION_TIME`: Duration of the generated SIWE message to sign. Defaults to 1 hour
- `SIWE_NONCE_CLEAN_INTERVAL`: Defines the interval (milliseconds) that the server will use to clean unused transports. Defaults to 1 hour
- `SIWE_NONCE_TTL`: Defines the time (milliseconds) that a SIWE nonce will still be considered valid after it was created. Defaults to 5 minutes
Either in `VINCENT_APP_ID` or in the `VINCENT_APP_JSON_DEFINITION` file, the App Id MUST be specified. So one of those values is required.

Consider that a SIWE message must have a valid nonce, so it will become invalid after reaching the expiration time or the nonce has been discarded.

You can set these environment variables in your shell before running the commands, or use a tool like `dotenvx`:

```bash
dotenvx run -f /path/to/.env -- npx @lit-protocol/vincent-mcp-server http
dotenvx run -f /path/to/.env -- npx -y @lit-protocol/vincent-mcp-server http
```

For an .env file example check [./.env.example](./.env.example)
Expand Down
3 changes: 3 additions & 0 deletions packages/apps/mcp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
"main": "./dist/src/bin/cli.js",
"scripts": {
"dev:http": "tsx watch --tsconfig ./tsconfig.app.json --env-file=.env src/bin/http.ts",
"dev:stdio": "tsx watch --tsconfig ./tsconfig.app.json --env-file=.env src/bin/stdio.ts",
"inspector": "npx @modelcontextprotocol/inspector",
"integration:openAI": "tsx --env-file=.env ./integrations/openAI.ts",
"integration:anthropic": "tsx --env-file=.env ./integrations/anthropic.ts"
Expand All @@ -44,12 +45,14 @@
"express": "^5.1.0",
"siwe": "^3.0.0",
"tslib": "^2.8.1",
"which": "^5.0.0",
"zod": "^3.25.64"
},
"devDependencies": {
"@anthropic-ai/sdk": "^0.52.0",
"@types/cors": "^2.8.19",
"@types/express": "^5.0.1",
"@types/which": "^3.0.4",
"openai": "^5.0.1",
"tsx": "^4.19.4"
}
Expand Down
Loading