1{
2 lib,
3 stdenv,
4 buildPythonPackage,
5 fetchFromGitHub,
6 writableTmpDirAsHomeHook,
7
8 # build-system
9 hatchling,
10 uv-dynamic-versioning,
11
12 # dependencies
13 authlib,
14 cyclopts,
15 exceptiongroup,
16 httpx,
17 mcp,
18 openai,
19 openapi-core,
20 openapi-pydantic,
21 pydantic,
22 pyperclip,
23 python-dotenv,
24 rich,
25 websockets,
26
27 # tests
28 dirty-equals,
29 email-validator,
30 fastapi,
31 inline-snapshot,
32 psutil,
33 pytest-asyncio,
34 pytest-httpx,
35 pytestCheckHook,
36}:
37
38buildPythonPackage rec {
39 pname = "fastmcp";
40 version = "2.12.4";
41 pyproject = true;
42
43 src = fetchFromGitHub {
44 owner = "jlowin";
45 repo = "fastmcp";
46 tag = "v${version}";
47 hash = "sha256-d8DOdyoyYDxZOpiUSxsYXnGrgFYN9CjdmAeHmJiDBP0=";
48 };
49
50 build-system = [
51 hatchling
52 uv-dynamic-versioning
53 ];
54
55 dependencies = [
56 authlib
57 cyclopts
58 exceptiongroup
59 httpx
60 mcp
61 openapi-core
62 openapi-pydantic
63 pydantic
64 pyperclip
65 python-dotenv
66 rich
67 websockets
68 ]
69 ++ pydantic.optional-dependencies.email;
70
71 optional-dependencies = {
72 openai = [ openai ];
73 };
74
75 pythonImportsCheck = [ "fastmcp" ];
76
77 nativeCheckInputs = [
78 dirty-equals
79 email-validator
80 fastapi
81 inline-snapshot
82 psutil
83 pytest-asyncio
84 pytest-httpx
85 pytestCheckHook
86 writableTmpDirAsHomeHook
87 ]
88 ++ lib.flatten (lib.attrValues optional-dependencies)
89 ++ inline-snapshot.optional-dependencies.dirty-equals;
90
91 disabledTests = [
92 "test_logging_middleware_with_payloads"
93 "test_structured_logging_middleware_produces_json"
94
95 # AssertionError: assert 'INFO' == 'DEBUG'
96 "test_temporary_settings"
97
98 # RuntimeError: Client failed to connect: Connection closed
99 "test_keep_alive_maintains_session_across_multiple_calls"
100 "test_keep_alive_false_starts_new_session_across_multiple_calls"
101 "test_keep_alive_false_exit_scope_kills_server"
102 "test_keep_alive_starts_new_session_if_manually_closed"
103 "test_keep_alive_true_exit_scope_kills_client"
104 "test_keep_alive_maintains_session_if_reentered"
105 "test_close_session_and_try_to_use_client_raises_error"
106 "test_parallel_calls"
107 "test_run_mcp_config"
108 "test_settings_from_environment_issue_1749"
109 "test_uv_transport"
110 "test_uv_transport_module"
111 "test_github_api_schema_performance"
112
113 # RuntimeError: Client failed to connect: Timed out while waiting for response
114 "test_timeout"
115 "test_timeout_tool_call_overrides_client_timeout_even_if_lower"
116
117 # assert 0 == 2
118 "test_multi_client"
119 "test_canonical_multi_client_with_transforms"
120
121 # AssertionError: assert {'annotations...object'}, ...} == {'annotations...sers']}}, ...}
122 "test_list_tools"
123
124 # fastmcp.exceptions.ToolError: Unknown tool
125 "test_multi_client_with_logging"
126 "test_multi_client_with_elicitation"
127 ]
128 ++ lib.optionals stdenv.hostPlatform.isDarwin [
129 # RuntimeError: Server failed to start after 10 attempts
130 "test_unauthorized_access"
131 ];
132
133 disabledTestPaths = lib.optionals stdenv.hostPlatform.isDarwin [
134 # RuntimeError: Server failed to start after 10 attempts
135 "tests/client/auth/test_oauth_client.py"
136 "tests/client/test_openapi_experimental.py"
137 "tests/client/test_openapi_legacy.py"
138 "tests/client/test_sse.py"
139 "tests/client/test_streamable_http.py"
140 "tests/server/auth/test_jwt_provider.py"
141 "tests/server/http/test_http_dependencies.py"
142 ];
143
144 __darwinAllowLocalNetworking = true;
145
146 meta = {
147 description = "Fast, Pythonic way to build MCP servers and clients";
148 changelog = "https://github.com/jlowin/fastmcp/releases/tag/${src.tag}";
149 homepage = "https://github.com/jlowin/fastmcp";
150 license = lib.licenses.asl20;
151 maintainers = with lib.maintainers; [ GaetanLepage ];
152 };
153}