mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-04-02 03:00:15 -04:00
Merge branch 'main' into security/git-server-optimization
This commit is contained in:
@@ -23,11 +23,13 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.18.0",
|
||||
"cors": "^2.8.5",
|
||||
"express": "^4.21.1",
|
||||
"zod": "^3.23.8",
|
||||
"zod-to-json-schema": "^3.23.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/cors": "^2.8.19",
|
||||
"@types/express": "^5.0.0",
|
||||
"shx": "^0.3.4",
|
||||
"typescript": "^5.6.2"
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
import { SSEServerTransport } from "@modelcontextprotocol/sdk/server/sse.js";
|
||||
import express from "express";
|
||||
import { createServer } from "./everything.js";
|
||||
import cors from 'cors';
|
||||
|
||||
console.error('Starting SSE server...');
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(cors({
|
||||
"origin": "*", // use "*" with caution in production
|
||||
"methods": "GET,POST",
|
||||
"preflightContinue": false,
|
||||
"optionsSuccessStatus": 204,
|
||||
})); // Enable CORS for all routes so Inspector can connect
|
||||
const transports: Map<string, SSEServerTransport> = new Map<string, SSEServerTransport>();
|
||||
|
||||
app.get("/sse", async (req, res) => {
|
||||
|
||||
@@ -3,10 +3,22 @@ import { InMemoryEventStore } from '@modelcontextprotocol/sdk/examples/shared/in
|
||||
import express, { Request, Response } from "express";
|
||||
import { createServer } from "./everything.js";
|
||||
import { randomUUID } from 'node:crypto';
|
||||
import cors from 'cors';
|
||||
|
||||
console.error('Starting Streamable HTTP server...');
|
||||
|
||||
const app = express();
|
||||
app.use(cors({
|
||||
"origin": "*", // use "*" with caution in production
|
||||
"methods": "GET,POST,DELETE",
|
||||
"preflightContinue": false,
|
||||
"optionsSuccessStatus": 204,
|
||||
"exposedHeaders": [
|
||||
'mcp-session-id',
|
||||
'last-event-id',
|
||||
'mcp-protocol-version'
|
||||
]
|
||||
})); // Enable CORS for all routes so Inspector can connect
|
||||
|
||||
const transports: Map<string, StreamableHTTPServerTransport> = new Map<string, StreamableHTTPServerTransport>();
|
||||
|
||||
@@ -15,6 +27,7 @@ app.post('/mcp', async (req: Request, res: Response) => {
|
||||
try {
|
||||
// Check for existing session ID
|
||||
const sessionId = req.headers['mcp-session-id'] as string | undefined;
|
||||
|
||||
let transport: StreamableHTTPServerTransport;
|
||||
|
||||
if (sessionId && transports.has(sessionId)) {
|
||||
|
||||
@@ -60,8 +60,18 @@ class KnowledgeGraphManager {
|
||||
|
||||
private async saveGraph(graph: KnowledgeGraph): Promise<void> {
|
||||
const lines = [
|
||||
...graph.entities.map(e => JSON.stringify({ type: "entity", ...e })),
|
||||
...graph.relations.map(r => JSON.stringify({ type: "relation", ...r })),
|
||||
...graph.entities.map(e => JSON.stringify({
|
||||
type: "entity",
|
||||
name: e.name,
|
||||
entityType: e.entityType,
|
||||
observations: e.observations
|
||||
})),
|
||||
...graph.relations.map(r => JSON.stringify({
|
||||
type: "relation",
|
||||
from: r.from,
|
||||
to: r.to,
|
||||
relationType: r.relationType
|
||||
})),
|
||||
];
|
||||
await fs.writeFile(MEMORY_FILE_PATH, lines.join("\n"));
|
||||
}
|
||||
@@ -219,10 +229,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
},
|
||||
},
|
||||
required: ["name", "entityType", "observations"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ["entities"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -241,10 +253,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
relationType: { type: "string", description: "The type of the relation" },
|
||||
},
|
||||
required: ["from", "to", "relationType"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ["relations"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -266,10 +280,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
},
|
||||
},
|
||||
required: ["entityName", "contents"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ["observations"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -285,6 +301,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
},
|
||||
},
|
||||
required: ["entityNames"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -306,10 +323,12 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
},
|
||||
},
|
||||
required: ["entityName", "observations"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
required: ["deletions"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -328,11 +347,13 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
relationType: { type: "string", description: "The type of the relation" },
|
||||
},
|
||||
required: ["from", "to", "relationType"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
description: "An array of relations to delete"
|
||||
},
|
||||
},
|
||||
required: ["relations"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -341,6 +362,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
inputSchema: {
|
||||
type: "object",
|
||||
properties: {},
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -352,6 +374,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
query: { type: "string", description: "The search query to match against entity names, types, and observation content" },
|
||||
},
|
||||
required: ["query"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
@@ -367,6 +390,7 @@ server.setRequestHandler(ListToolsRequestSchema, async () => {
|
||||
},
|
||||
},
|
||||
required: ["names"],
|
||||
additionalProperties: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@@ -46,7 +46,8 @@ def get_local_tz(local_tz_override: str | None = None) -> ZoneInfo:
|
||||
local_tzname = get_localzone_name()
|
||||
if local_tzname is not None:
|
||||
return ZoneInfo(local_tzname)
|
||||
raise McpError("Could not determine local timezone - tzinfo is None")
|
||||
# Default to UTC if local timezone cannot be determined
|
||||
return ZoneInfo("UTC")
|
||||
|
||||
|
||||
def get_zoneinfo(timezone_name: str) -> ZoneInfo:
|
||||
|
||||
@@ -486,10 +486,10 @@ def test_get_local_tz_with_valid_iana_name(mock_get_localzone):
|
||||
|
||||
@patch('mcp_server_time.server.get_localzone_name')
|
||||
def test_get_local_tz_when_none_returned(mock_get_localzone):
|
||||
"""Test error when tzlocal returns None."""
|
||||
"""Test default to UTC when tzlocal returns None."""
|
||||
mock_get_localzone.return_value = None
|
||||
with pytest.raises(McpError, match="Could not determine local timezone"):
|
||||
get_local_tz()
|
||||
result = get_local_tz()
|
||||
assert str(result) == "UTC"
|
||||
|
||||
|
||||
@patch('mcp_server_time.server.get_localzone_name')
|
||||
|
||||
Reference in New Issue
Block a user