mirror of
https://github.com/modelcontextprotocol/servers.git
synced 2026-02-19 11:54:58 -05:00
Merge branch 'main' into add-tasks-support
This commit is contained in:
9
package-lock.json
generated
9
package-lock.json
generated
@@ -1688,9 +1688,10 @@
|
||||
}
|
||||
},
|
||||
"node_modules/diff": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
|
||||
"integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
|
||||
"version": "8.0.3",
|
||||
"resolved": "https://registry.npmjs.org/diff/-/diff-8.0.3.tgz",
|
||||
"integrity": "sha512-qejHi7bcSD4hQAZE0tNAawRK1ZtafHDmMTMkrrIGgSLl7hTnQHmKCeB45xAcbfTqK2zowkM3j3bHt/4b/ARbYQ==",
|
||||
"license": "BSD-3-Clause",
|
||||
"engines": {
|
||||
"node": ">=0.3.1"
|
||||
}
|
||||
@@ -3804,7 +3805,7 @@
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.25.2",
|
||||
"diff": "^5.1.0",
|
||||
"diff": "^8.0.3",
|
||||
"glob": "^10.5.0",
|
||||
"minimatch": "^10.0.1",
|
||||
"zod-to-json-schema": "^3.23.5"
|
||||
|
||||
@@ -30,7 +30,7 @@ export const roots: Map<string | undefined, Root[]> = new Map<
|
||||
*/
|
||||
export const syncRoots = async (server: McpServer, sessionId?: string) => {
|
||||
const clientCapabilities = server.server.getClientCapabilities() || {};
|
||||
const clientSupportsRoots: boolean = clientCapabilities.roots !== undefined;
|
||||
const clientSupportsRoots: boolean = clientCapabilities?.roots !== undefined;
|
||||
|
||||
// Fetch the roots list for this client
|
||||
if (clientSupportsRoots) {
|
||||
@@ -48,7 +48,7 @@ export const syncRoots = async (server: McpServer, sessionId?: string) => {
|
||||
{
|
||||
level: "info",
|
||||
logger: "everything-server",
|
||||
data: `Roots updated: ${response.roots.length} root(s) received from client`,
|
||||
data: `Roots updated: ${response?.roots?.length} root(s) received from client`,
|
||||
},
|
||||
sessionId
|
||||
);
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
},
|
||||
"dependencies": {
|
||||
"@modelcontextprotocol/sdk": "^1.25.2",
|
||||
"diff": "^5.1.0",
|
||||
"diff": "^8.0.3",
|
||||
"glob": "^10.5.0",
|
||||
"minimatch": "^10.0.1",
|
||||
"zod-to-json-schema": "^3.23.5"
|
||||
|
||||
@@ -390,5 +390,94 @@ describe('KnowledgeGraphManager', () => {
|
||||
expect(JSON.parse(lines[0])).toHaveProperty('type', 'entity');
|
||||
expect(JSON.parse(lines[1])).toHaveProperty('type', 'relation');
|
||||
});
|
||||
|
||||
it('should strip type field from entities when loading from file', async () => {
|
||||
// Create entities and relations (these get saved with type field)
|
||||
await manager.createEntities([
|
||||
{ name: 'Alice', entityType: 'person', observations: ['test observation'] },
|
||||
{ name: 'Bob', entityType: 'person', observations: [] },
|
||||
]);
|
||||
await manager.createRelations([
|
||||
{ from: 'Alice', to: 'Bob', relationType: 'knows' },
|
||||
]);
|
||||
|
||||
// Verify file contains type field (order may vary)
|
||||
const fileContent = await fs.readFile(testFilePath, 'utf-8');
|
||||
const fileLines = fileContent.split('\n').filter(line => line.trim());
|
||||
const fileItems = fileLines.map(line => JSON.parse(line));
|
||||
const fileEntity = fileItems.find(item => item.type === 'entity');
|
||||
const fileRelation = fileItems.find(item => item.type === 'relation');
|
||||
expect(fileEntity).toBeDefined();
|
||||
expect(fileEntity).toHaveProperty('type', 'entity');
|
||||
expect(fileRelation).toBeDefined();
|
||||
expect(fileRelation).toHaveProperty('type', 'relation');
|
||||
|
||||
// Create new manager instance to force reload from file
|
||||
const manager2 = new KnowledgeGraphManager(testFilePath);
|
||||
const graph = await manager2.readGraph();
|
||||
|
||||
// Verify loaded entities don't have type field
|
||||
expect(graph.entities).toHaveLength(2);
|
||||
graph.entities.forEach(entity => {
|
||||
expect(entity).not.toHaveProperty('type');
|
||||
expect(entity).toHaveProperty('name');
|
||||
expect(entity).toHaveProperty('entityType');
|
||||
expect(entity).toHaveProperty('observations');
|
||||
});
|
||||
|
||||
// Verify loaded relations don't have type field
|
||||
expect(graph.relations).toHaveLength(1);
|
||||
graph.relations.forEach(relation => {
|
||||
expect(relation).not.toHaveProperty('type');
|
||||
expect(relation).toHaveProperty('from');
|
||||
expect(relation).toHaveProperty('to');
|
||||
expect(relation).toHaveProperty('relationType');
|
||||
});
|
||||
});
|
||||
|
||||
it('should strip type field from searchNodes results', async () => {
|
||||
await manager.createEntities([
|
||||
{ name: 'Alice', entityType: 'person', observations: ['works at Acme'] },
|
||||
]);
|
||||
await manager.createRelations([
|
||||
{ from: 'Alice', to: 'Alice', relationType: 'self' },
|
||||
]);
|
||||
|
||||
// Create new manager instance to force reload from file
|
||||
const manager2 = new KnowledgeGraphManager(testFilePath);
|
||||
const result = await manager2.searchNodes('Alice');
|
||||
|
||||
// Verify search results don't have type field
|
||||
expect(result.entities).toHaveLength(1);
|
||||
expect(result.entities[0]).not.toHaveProperty('type');
|
||||
expect(result.entities[0].name).toBe('Alice');
|
||||
|
||||
expect(result.relations).toHaveLength(1);
|
||||
expect(result.relations[0]).not.toHaveProperty('type');
|
||||
expect(result.relations[0].from).toBe('Alice');
|
||||
});
|
||||
|
||||
it('should strip type field from openNodes results', async () => {
|
||||
await manager.createEntities([
|
||||
{ name: 'Alice', entityType: 'person', observations: [] },
|
||||
{ name: 'Bob', entityType: 'person', observations: [] },
|
||||
]);
|
||||
await manager.createRelations([
|
||||
{ from: 'Alice', to: 'Bob', relationType: 'knows' },
|
||||
]);
|
||||
|
||||
// Create new manager instance to force reload from file
|
||||
const manager2 = new KnowledgeGraphManager(testFilePath);
|
||||
const result = await manager2.openNodes(['Alice', 'Bob']);
|
||||
|
||||
// Verify open results don't have type field
|
||||
expect(result.entities).toHaveLength(2);
|
||||
result.entities.forEach(entity => {
|
||||
expect(entity).not.toHaveProperty('type');
|
||||
});
|
||||
|
||||
expect(result.relations).toHaveLength(1);
|
||||
expect(result.relations[0]).not.toHaveProperty('type');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -74,8 +74,20 @@ export class KnowledgeGraphManager {
|
||||
const lines = data.split("\n").filter(line => line.trim() !== "");
|
||||
return lines.reduce((graph: KnowledgeGraph, line) => {
|
||||
const item = JSON.parse(line);
|
||||
if (item.type === "entity") graph.entities.push(item as Entity);
|
||||
if (item.type === "relation") graph.relations.push(item as Relation);
|
||||
if (item.type === "entity") {
|
||||
graph.entities.push({
|
||||
name: item.name,
|
||||
entityType: item.entityType,
|
||||
observations: item.observations
|
||||
});
|
||||
}
|
||||
if (item.type === "relation") {
|
||||
graph.relations.push({
|
||||
from: item.from,
|
||||
to: item.to,
|
||||
relationType: item.relationType
|
||||
});
|
||||
}
|
||||
return graph;
|
||||
}, { entities: [], relations: [] });
|
||||
} catch (error) {
|
||||
|
||||
@@ -17,10 +17,10 @@ classifiers = [
|
||||
"Programming Language :: Python :: 3.10",
|
||||
]
|
||||
dependencies = [
|
||||
"mcp>=1.0.0",
|
||||
"mcp>=1.23.0",
|
||||
"pydantic>=2.0.0",
|
||||
"tzdata>=2024.2",
|
||||
"tzlocal>=5.3.1"
|
||||
"tzlocal>=5.3.1",
|
||||
]
|
||||
|
||||
[project.scripts]
|
||||
|
||||
@@ -8,7 +8,7 @@ from tzlocal import get_localzone_name # ← returns "Europe/Paris", etc.
|
||||
|
||||
from mcp.server import Server
|
||||
from mcp.server.stdio import stdio_server
|
||||
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource
|
||||
from mcp.types import Tool, TextContent, ImageContent, EmbeddedResource, ErrorData, INVALID_PARAMS
|
||||
from mcp.shared.exceptions import McpError
|
||||
|
||||
from pydantic import BaseModel
|
||||
@@ -54,7 +54,7 @@ def get_zoneinfo(timezone_name: str) -> ZoneInfo:
|
||||
try:
|
||||
return ZoneInfo(timezone_name)
|
||||
except Exception as e:
|
||||
raise McpError(f"Invalid timezone: {str(e)}")
|
||||
raise McpError(ErrorData(code=INVALID_PARAMS, message=f"Invalid timezone: {str(e)}"))
|
||||
|
||||
|
||||
class TimeServer:
|
||||
|
||||
818
src/time/uv.lock
generated
818
src/time/uv.lock
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user