From 6a50ecadc264a12611ed30998059883f3c0f6021 Mon Sep 17 00:00:00 2001 From: Al Joslin Date: Sat, 5 Apr 2025 19:34:29 -0400 Subject: [PATCH 1/8] read_graph takes no args --- src/memory/index.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/memory/index.ts b/src/memory/index.ts index 62f7aeb6..1f078c54 100644 --- a/src/memory/index.ts +++ b/src/memory/index.ts @@ -376,6 +376,10 @@ server.setRequestHandler(ListToolsRequestSchema, async () => { server.setRequestHandler(CallToolRequestSchema, async (request) => { const { name, arguments: args } = request.params; + if (name === "read_graph") { + return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.readGraph(), null, 2) }] }; + } + if (!args) { throw new Error(`No arguments provided for tool: ${name}`); } @@ -396,8 +400,6 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { case "delete_relations": await knowledgeGraphManager.deleteRelations(args.relations as Relation[]); return { content: [{ type: "text", text: "Relations deleted successfully" }] }; - case "read_graph": - return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.readGraph(), null, 2) }] }; case "search_nodes": return { content: [{ type: "text", text: JSON.stringify(await knowledgeGraphManager.searchNodes(args.query as string), null, 2) }] }; case "open_nodes": From 4b9e32d179647c22caba9f1551a69fbe7ac17bda Mon Sep 17 00:00:00 2001 From: Al Joslin Date: Sat, 5 Apr 2025 19:52:28 -0400 Subject: [PATCH 2/8] explains how not to get confused --- src/memory/README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/memory/README.md b/src/memory/README.md index e5795cb5..1d496a2a 100644 --- a/src/memory/README.md +++ b/src/memory/README.md @@ -221,6 +221,8 @@ Docker: docker build -t mcp/memory -f src/memory/Dockerfile . ``` +Note: when upgrading a combination of docker usage and a docker volume for storage, delete the previous index.js file from the old docker volume before starting the new container so this new index.js is not overwritten. + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. From 045b15a6149d01e3370409da580be9b206384a20 Mon Sep 17 00:00:00 2001 From: Al Joslin Date: Sat, 5 Apr 2025 19:55:36 -0400 Subject: [PATCH 3/8] maybe AI makes more sense --- src/memory/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/memory/README.md b/src/memory/README.md index 1d496a2a..928680c9 100644 --- a/src/memory/README.md +++ b/src/memory/README.md @@ -221,7 +221,7 @@ Docker: docker build -t mcp/memory -f src/memory/Dockerfile . ``` -Note: when upgrading a combination of docker usage and a docker volume for storage, delete the previous index.js file from the old docker volume before starting the new container so this new index.js is not overwritten. +For Awareness: a prior mcp/memory volume contains an index.js file that could be overwritten by the new container. If you are using a docker volume for storage, delete the old docker volume's `index.js` file before starting the new container. ## License From dcd814fd2aa23335b0a36bffae776304502170c0 Mon Sep 17 00:00:00 2001 From: Koichi ITO Date: Sat, 12 Apr 2025 16:39:38 +0900 Subject: [PATCH 4/8] [Doc] Use the official spelling of "TypeScript" in README This PR replaces all instances of "Typescript" with the official capitalization "TypeScript". The term is spelled "TypeScript" in the linked document. Revert "[Doc] Use the official spelling of "TypeScript" in README" This reverts commit 97db4264802aab50ecb456e1b289f93e439af485. --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 57ac8cc7..4b01ad96 100644 --- a/README.md +++ b/README.md @@ -109,7 +109,7 @@ Official integrations are maintained by companies building production ready MCP - BrowserStack Logo **[BrowserStack](https://github.com/browserstack/mcp-server)** - Access BrowserStack's [Test Platform](https://www.browserstack.com/test-platform) to debug, write and fix tests, do accessibility testing and more. - Bucket **[Bucket](https://github.com/bucketco/bucket-javascript-sdk/tree/main/packages/cli#model-context-protocol)** - Flag features, manage company data, and control feature access using [Bucket](https://bucket.co) - Buildkite Logo **[Buildkite](https://github.com/buildkite/buildkite-mcp-server)** - Exposing Buildkite data (pipelines, builds, jobs, tests) to AI tooling and editors. -- Buildable Logo**[Buildable](https://github.com/chunkydotdev/bldbl-mcp)** (Typescript) - Official MCP server for Buildable AI-powered development platform. Enables AI assistants to manage tasks, track progress, get project context, and collaborate with humans on software projects. +- Buildable Logo**[Buildable](https://github.com/chunkydotdev/bldbl-mcp)** (TypeScript) - Official MCP server for Buildable AI-powered development platform. Enables AI assistants to manage tasks, track progress, get project context, and collaborate with humans on software projects. - BuiltWith Logo **[BuiltWith](https://github.com/builtwith/mcp)** - Identify the technology stack behind any website. - PortSwigger Logo **[Burp Suite](https://github.com/PortSwigger/mcp-server)** - MCP Server extension allowing AI clients to connect to [Burp Suite](https://portswigger.net) - Campertunity Logo **[Campertunity](https://github.com/campertunity/mcp-server)** - Search campgrounds around the world on campertunity, check availability, and provide booking links. @@ -1067,17 +1067,17 @@ These are high-level frameworks that make it easier to build MCP servers or clie * **[Foxy Contexts](https://github.com/strowk/foxy-contexts)** – A library to build MCP servers in Golang by **[strowk](https://github.com/strowk)** * **[Higress MCP Server Hosting](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/mcp-servers)** - A solution for hosting MCP Servers by extending the API Gateway (based on Envoy) with wasm plugins. * **[MCP Declarative Java SDK](https://github.com/codeboyzhou/mcp-declarative-java-sdk)** Annotation-driven MCP servers development with Java, no Spring Framework Required, minimize dependencies as much as possible. -* **[MCP-Framework](https://mcp-framework.com)** Build MCP servers with elegance and speed in Typescript. Comes with a CLI to create your project with `mcp create app`. Get started with your first server in under 5 minutes by **[Alex Andru](https://github.com/QuantGeekDev)** +* **[MCP-Framework](https://mcp-framework.com)** Build MCP servers with elegance and speed in TypeScript. Comes with a CLI to create your project with `mcp create app`. Get started with your first server in under 5 minutes by **[Alex Andru](https://github.com/QuantGeekDev)** * **[MCP Plexus](https://github.com/Super-I-Tech/mcp_plexus)**: A secure, **multi-tenant** and Multi-user MCP python server framework built to integrate easily with external services via OAuth 2.1, offering scalable and robust solutions for managing complex AI applications. * **[mcp_sse (Elixir)](https://github.com/kEND/mcp_sse)** An SSE implementation in Elixir for rapidly creating MCP servers. -* **[Next.js MCP Server Template](https://github.com/vercel-labs/mcp-for-next.js)** (Typescript) - A starter Next.js project that uses the MCP Adapter to allow MCP clients to connect and access resources. +* **[Next.js MCP Server Template](https://github.com/vercel-labs/mcp-for-next.js)** (TypeScript) - A starter Next.js project that uses the MCP Adapter to allow MCP clients to connect and access resources. * **[Quarkus MCP Server SDK](https://github.com/quarkiverse/quarkus-mcp-server)** (Java) - **[R mcptools](https://github.com/posit-dev/mcptools)** - An R SDK for creating R-based MCP servers and retrieving functionality from third-party MCP servers as R functions. * **[SAP ABAP MCP Server SDK](https://github.com/abap-ai/mcp)** - Build SAP ABAP based MCP servers. ABAP 7.52 based with 7.02 downport; runs on R/3 & S/4HANA on-premises, currently not cloud-ready. * **[Spring AI MCP Server](https://docs.spring.io/spring-ai/reference/api/mcp/mcp-server-boot-starter-docs.html)** - Provides auto-configuration for setting up an MCP server in Spring Boot applications. * **[Template MCP Server](https://github.com/mcpdotdirect/template-mcp-server)** - A CLI tool to create a new Model Context Protocol server project with TypeScript support, dual transport options, and an extensible structure * **[AgentR Universal MCP SDK](https://github.com/universal-mcp/universal-mcp)** - A python SDK to build MCP Servers with inbuilt credential management by **[Agentr](https://agentr.dev/home)** -* **[Vercel MCP Adapter](https://github.com/vercel/mcp-adapter)** (Typescript) - A simple package to start serving an MCP server on most major JS meta-frameworks including Next, Nuxt, Svelte, and more. +* **[Vercel MCP Adapter](https://github.com/vercel/mcp-adapter)** (TypeScript) - A simple package to start serving an MCP server on most major JS meta-frameworks including Next, Nuxt, Svelte, and more. * **[Hermes MCP](https://github.com/cloudwalk/hermes-mcp)** (Elixir) - A high-performance and high-level Model Context Protocol (MCP) implementation in Elixir. Think like "Live View" for MCP. @@ -1143,7 +1143,7 @@ Additional resources on MCP. ## 🚀 Getting Started ### Using MCP Servers in this Repository -Typescript-based servers in this repository can be used directly with `npx`. +TypeScript-based servers in this repository can be used directly with `npx`. For example, this will start the [Memory](src/memory) server: ```sh From 2b041eef88a386dca3d8555384baa2d7c6558597 Mon Sep 17 00:00:00 2001 From: Adam Jones Date: Fri, 1 Aug 2025 19:08:14 +0100 Subject: [PATCH 5/8] time: Add tests for local timezone detection and handling in get_local_tz function --- src/time/test/time_server_test.py | 70 ++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/time/test/time_server_test.py b/src/time/test/time_server_test.py index 8129fb5b..97a6ea1f 100644 --- a/src/time/test/time_server_test.py +++ b/src/time/test/time_server_test.py @@ -2,8 +2,10 @@ from freezegun import freeze_time from mcp.shared.exceptions import McpError import pytest +from unittest.mock import patch +from zoneinfo import ZoneInfo -from mcp_server_time.server import TimeServer +from mcp_server_time.server import TimeServer, get_local_tz @pytest.mark.parametrize( @@ -458,3 +460,69 @@ def test_convert_time(test_time, source_tz, time_str, target_tz, expected): assert result.source.is_dst == expected["source"]["is_dst"] assert result.target.is_dst == expected["target"]["is_dst"] assert result.time_difference == expected["time_difference"] + + +def test_get_local_tz_with_override(): + """Test that timezone override works correctly.""" + result = get_local_tz("America/New_York") + assert str(result) == "America/New_York" + assert isinstance(result, ZoneInfo) + + +def test_get_local_tz_with_invalid_override(): + """Test that invalid timezone override raises an error.""" + with pytest.raises(Exception): # ZoneInfo will raise an exception + get_local_tz("Invalid/Timezone") + + +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_with_valid_iana_name(mock_get_localzone): + """Test that valid IANA timezone names from tzlocal work correctly.""" + mock_get_localzone.return_value = "Europe/London" + result = get_local_tz() + assert str(result) == "Europe/London" + assert isinstance(result, ZoneInfo) + + +@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.""" + mock_get_localzone.return_value = None + with pytest.raises(McpError, match="Could not determine local timezone"): + get_local_tz() + + +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_handles_windows_timezones(mock_get_localzone): + """Test that tzlocal properly handles Windows timezone names. + + Note: tzlocal should convert Windows names like 'Pacific Standard Time' + to proper IANA names like 'America/Los_Angeles'. + """ + # tzlocal should return IANA names even on Windows + mock_get_localzone.return_value = "America/Los_Angeles" + result = get_local_tz() + assert str(result) == "America/Los_Angeles" + assert isinstance(result, ZoneInfo) + + +@pytest.mark.parametrize( + "timezone_name", + [ + "America/New_York", + "Europe/Paris", + "Asia/Tokyo", + "Australia/Sydney", + "Africa/Cairo", + "America/Sao_Paulo", + "Pacific/Auckland", + "UTC", + ], +) +@patch('mcp_server_time.server.get_localzone_name') +def test_get_local_tz_various_timezones(mock_get_localzone, timezone_name): + """Test various timezone names that tzlocal might return.""" + mock_get_localzone.return_value = timezone_name + result = get_local_tz() + assert str(result) == timezone_name + assert isinstance(result, ZoneInfo) From 4c192aee939b73aabb9cbe3671b6224452fec480 Mon Sep 17 00:00:00 2001 From: evalstate <1936278+evalstate@users.noreply.github.com> Date: Sat, 2 Aug 2025 08:46:33 +0100 Subject: [PATCH 6/8] Remove out-of-specification notifications/stderr sending --- src/everything/everything.ts | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/src/everything/everything.ts b/src/everything/everything.ts index f1a2a11d..26e43521 100644 --- a/src/everything/everything.ts +++ b/src/everything/everything.ts @@ -209,18 +209,6 @@ export const createServer = () => { }, 20000); - // Set up update interval for stderr messages - stdErrUpdateInterval = setInterval(() => { - const shortTimestamp = new Date().toLocaleTimeString([], { - hour: "2-digit", - minute: "2-digit", - second: "2-digit" - }); - server.notification({ - method: "notifications/stderr", - params: { content: `${shortTimestamp}: A stderr message` }, - }); - }, 30000); // Helper method to request sampling from client const requestSampling = async ( From b43ecf8710e3c31f90daf69127b4726dfb1f0f63 Mon Sep 17 00:00:00 2001 From: evalstate <1936278+evalstate@users.noreply.github.com> Date: Sat, 2 Aug 2025 10:13:32 +0100 Subject: [PATCH 7/8] 1) Update README to contain basic build/run instructions. Remove legacy test advice. 2) Make the Unit Test insensitive to the git default branch name --- src/git/README.md | 50 +++++++++++++++--------------------- src/git/tests/test_server.py | 11 +++++--- 2 files changed, 27 insertions(+), 34 deletions(-) diff --git a/src/git/README.md b/src/git/README.md index a1294d8c..30b7e2d8 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -285,13 +285,29 @@ help you debug any issues. ## Development -If you are doing local development, there are two ways to test your changes: +### Building -1. Run the MCP inspector to test your changes. See [Debugging](#debugging) for run instructions. +[`uv`](https://docs.astral.sh/uv/) is used for development. -2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`: +Start by creating a fresh virtual environment: -### Docker +```bash +uv venv +source .venv/bin/activate +``` +To run the tests, type `uv run pytest`, to run the server from source use `uv run src/mcp_server_git/`. + +To build, type `uv build`. You can then now run `mcp-server-git` command directly. Open with the inspector using `npx @modelcontextprotocol/inspector@latest mcp-server-git`. + +To specify the Python version type `uv python pin ` (useful if you want to use a more recent version than the default). + +To create the Docker container use + +```bash +docker build -t mcp/git . +``` + +An example showing how to run via the Docker container is below: ```json { @@ -312,32 +328,6 @@ If you are doing local development, there are two ways to test your changes: } ``` -### UVX -```json -{ -"mcpServers": { - "git": { - "command": "uv", - "args": [ - "--directory", - "//mcp-servers/src/git", - "run", - "mcp-server-git" - ] - } - } -} -``` - -## Build - -Docker build: - -```bash -cd src/git -docker build -t mcp/git . -``` - ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index 911a90cf..ceeeab91 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -12,6 +12,9 @@ def test_repository(tmp_path: Path): Path(repo_path / "test.txt").write_text("test") test_repo.index.add(["test.txt"]) test_repo.index.commit("initial commit") + + # Store the default branch name on the repo object for tests to use + test_repo.default_branch = test_repo.active_branch.name yield test_repo @@ -51,11 +54,11 @@ def test_git_branch_contains(test_repository): Path(test_repository.working_dir / Path("feature.txt")).write_text("feature content") test_repository.index.add(["feature.txt"]) commit = test_repository.index.commit("feature commit") - test_repository.git.checkout("master") + test_repository.git.checkout(test_repository.default_branch) result = git_branch(test_repository, "local", contains=commit.hexsha) assert "feature-branch" in result - assert "master" not in result + assert test_repository.default_branch not in result def test_git_branch_not_contains(test_repository): # Create a new branch and commit to it @@ -63,8 +66,8 @@ def test_git_branch_not_contains(test_repository): Path(test_repository.working_dir / Path("another_feature.txt")).write_text("another feature content") test_repository.index.add(["another_feature.txt"]) commit = test_repository.index.commit("another feature commit") - test_repository.git.checkout("master") + test_repository.git.checkout(test_repository.default_branch) result = git_branch(test_repository, "local", not_contains=commit.hexsha) assert "another-feature-branch" not in result - assert "master" in result + assert test_repository.default_branch in result From 3a297d843253b8196ed6d33ec7820267729df02b Mon Sep 17 00:00:00 2001 From: evalstate <1936278+evalstate@users.noreply.github.com> Date: Sat, 2 Aug 2025 10:17:05 +0100 Subject: [PATCH 8/8] Revert "1) Update README to contain basic build/run instructions. Remove legacy test advice." (wrong branch push) This reverts commit b43ecf8710e3c31f90daf69127b4726dfb1f0f63. --- src/git/README.md | 50 +++++++++++++++++++++--------------- src/git/tests/test_server.py | 11 +++----- 2 files changed, 34 insertions(+), 27 deletions(-) diff --git a/src/git/README.md b/src/git/README.md index 30b7e2d8..a1294d8c 100644 --- a/src/git/README.md +++ b/src/git/README.md @@ -285,29 +285,13 @@ help you debug any issues. ## Development -### Building +If you are doing local development, there are two ways to test your changes: -[`uv`](https://docs.astral.sh/uv/) is used for development. +1. Run the MCP inspector to test your changes. See [Debugging](#debugging) for run instructions. -Start by creating a fresh virtual environment: +2. Test using the Claude desktop app. Add the following to your `claude_desktop_config.json`: -```bash -uv venv -source .venv/bin/activate -``` -To run the tests, type `uv run pytest`, to run the server from source use `uv run src/mcp_server_git/`. - -To build, type `uv build`. You can then now run `mcp-server-git` command directly. Open with the inspector using `npx @modelcontextprotocol/inspector@latest mcp-server-git`. - -To specify the Python version type `uv python pin ` (useful if you want to use a more recent version than the default). - -To create the Docker container use - -```bash -docker build -t mcp/git . -``` - -An example showing how to run via the Docker container is below: +### Docker ```json { @@ -328,6 +312,32 @@ An example showing how to run via the Docker container is below: } ``` +### UVX +```json +{ +"mcpServers": { + "git": { + "command": "uv", + "args": [ + "--directory", + "//mcp-servers/src/git", + "run", + "mcp-server-git" + ] + } + } +} +``` + +## Build + +Docker build: + +```bash +cd src/git +docker build -t mcp/git . +``` + ## License This MCP server is licensed under the MIT License. This means you are free to use, modify, and distribute the software, subject to the terms and conditions of the MIT License. For more details, please see the LICENSE file in the project repository. diff --git a/src/git/tests/test_server.py b/src/git/tests/test_server.py index ceeeab91..911a90cf 100644 --- a/src/git/tests/test_server.py +++ b/src/git/tests/test_server.py @@ -12,9 +12,6 @@ def test_repository(tmp_path: Path): Path(repo_path / "test.txt").write_text("test") test_repo.index.add(["test.txt"]) test_repo.index.commit("initial commit") - - # Store the default branch name on the repo object for tests to use - test_repo.default_branch = test_repo.active_branch.name yield test_repo @@ -54,11 +51,11 @@ def test_git_branch_contains(test_repository): Path(test_repository.working_dir / Path("feature.txt")).write_text("feature content") test_repository.index.add(["feature.txt"]) commit = test_repository.index.commit("feature commit") - test_repository.git.checkout(test_repository.default_branch) + test_repository.git.checkout("master") result = git_branch(test_repository, "local", contains=commit.hexsha) assert "feature-branch" in result - assert test_repository.default_branch not in result + assert "master" not in result def test_git_branch_not_contains(test_repository): # Create a new branch and commit to it @@ -66,8 +63,8 @@ def test_git_branch_not_contains(test_repository): Path(test_repository.working_dir / Path("another_feature.txt")).write_text("another feature content") test_repository.index.add(["another_feature.txt"]) commit = test_repository.index.commit("another feature commit") - test_repository.git.checkout(test_repository.default_branch) + test_repository.git.checkout("master") result = git_branch(test_repository, "local", not_contains=commit.hexsha) assert "another-feature-branch" not in result - assert test_repository.default_branch in result + assert "master" in result