fastmcp 0.2.0__py3-none-any.whl → 0.3.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,4 @@
1
+ from .base import Tool
2
+ from .tool_manager import ToolManager
3
+
4
+ __all__ = ["Tool", "ToolManager"]
fastmcp/tools/base.py ADDED
@@ -0,0 +1,79 @@
1
+ import fastmcp
2
+ from fastmcp.exceptions import ToolError
3
+
4
+
5
+ from pydantic import BaseModel, Field, TypeAdapter, validate_call
6
+
7
+
8
+ import inspect
9
+ from typing import TYPE_CHECKING, Any, Callable, Optional
10
+
11
+ if TYPE_CHECKING:
12
+ from fastmcp.server import Context
13
+
14
+
15
+ class Tool(BaseModel):
16
+ """Internal tool registration info."""
17
+
18
+ fn: Callable = Field(exclude=True)
19
+ name: str = Field(description="Name of the tool")
20
+ description: str = Field(description="Description of what the tool does")
21
+ parameters: dict = Field(description="JSON schema for tool parameters")
22
+ is_async: bool = Field(description="Whether the tool is async")
23
+ context_kwarg: Optional[str] = Field(
24
+ None, description="Name of the kwarg that should receive context"
25
+ )
26
+
27
+ @classmethod
28
+ def from_function(
29
+ cls,
30
+ fn: Callable,
31
+ name: Optional[str] = None,
32
+ description: Optional[str] = None,
33
+ context_kwarg: Optional[str] = None,
34
+ ) -> "Tool":
35
+ """Create a Tool from a function."""
36
+ func_name = name or fn.__name__
37
+
38
+ if func_name == "<lambda>":
39
+ raise ValueError("You must provide a name for lambda functions")
40
+
41
+ func_doc = description or fn.__doc__ or ""
42
+ is_async = inspect.iscoroutinefunction(fn)
43
+
44
+ # Get schema from TypeAdapter - will fail if function isn't properly typed
45
+ parameters = TypeAdapter(fn).json_schema()
46
+
47
+ # Find context parameter if it exists
48
+ if context_kwarg is None:
49
+ sig = inspect.signature(fn)
50
+ for param_name, param in sig.parameters.items():
51
+ if param.annotation is fastmcp.Context:
52
+ context_kwarg = param_name
53
+ break
54
+
55
+ # ensure the arguments are properly cast
56
+ fn = validate_call(fn)
57
+
58
+ return cls(
59
+ fn=fn,
60
+ name=func_name,
61
+ description=func_doc,
62
+ parameters=parameters,
63
+ is_async=is_async,
64
+ context_kwarg=context_kwarg,
65
+ )
66
+
67
+ async def run(self, arguments: dict, context: Optional["Context"] = None) -> Any:
68
+ """Run the tool with arguments."""
69
+ try:
70
+ # Inject context if needed
71
+ if self.context_kwarg:
72
+ arguments[self.context_kwarg] = context
73
+
74
+ # Call function with proper async handling
75
+ if self.is_async:
76
+ return await self.fn(**arguments)
77
+ return self.fn(**arguments)
78
+ except Exception as e:
79
+ raise ToolError(f"Error executing tool {self.name}: {e}") from e
@@ -0,0 +1,55 @@
1
+ from fastmcp.exceptions import ToolError
2
+
3
+ from fastmcp.tools.base import Tool
4
+
5
+
6
+ from typing import Any, Callable, Dict, Optional, TYPE_CHECKING
7
+
8
+ from fastmcp.utilities.logging import get_logger
9
+
10
+ if TYPE_CHECKING:
11
+ from fastmcp.server import Context
12
+
13
+ logger = get_logger(__name__)
14
+
15
+
16
+ class ToolManager:
17
+ """Manages FastMCP tools."""
18
+
19
+ def __init__(self, warn_on_duplicate_tools: bool = True):
20
+ self._tools: Dict[str, Tool] = {}
21
+ self.warn_on_duplicate_tools = warn_on_duplicate_tools
22
+
23
+ def get_tool(self, name: str) -> Optional[Tool]:
24
+ """Get tool by name."""
25
+ return self._tools.get(name)
26
+
27
+ def list_tools(self) -> list[Tool]:
28
+ """List all registered tools."""
29
+ return list(self._tools.values())
30
+
31
+ def add_tool(
32
+ self,
33
+ fn: Callable,
34
+ name: Optional[str] = None,
35
+ description: Optional[str] = None,
36
+ ) -> Tool:
37
+ """Add a tool to the server."""
38
+ tool = Tool.from_function(fn, name=name, description=description)
39
+ existing = self._tools.get(tool.name)
40
+ if existing:
41
+ if self.warn_on_duplicate_tools:
42
+ logger.warning(f"Tool already exists: {tool.name}")
43
+ return existing
44
+ self._tools[tool.name] = tool
45
+ return tool
46
+
47
+ async def call_tool(
48
+ self, name: str, arguments: dict, context: Optional["Context"] = None
49
+ ) -> Any:
50
+ """Call a tool by name with arguments."""
51
+ tool = self.get_tool(name)
52
+ if not tool:
53
+ raise ToolError(f"Unknown tool: {name}")
54
+
55
+ return await tool.run(arguments, context=context)
@@ -3,15 +3,17 @@
3
3
  import logging
4
4
  from typing import Literal
5
5
 
6
+ from rich.logging import RichHandler
7
+
6
8
 
7
9
  def get_logger(name: str) -> logging.Logger:
8
10
  """Get a logger nested under FastMCP namespace.
9
11
 
10
12
  Args:
11
- name: The name of the logger, which will be prefixed with 'FastMCP.'
13
+ name: the name of the logger, which will be prefixed with 'FastMCP.'
12
14
 
13
15
  Returns:
14
- A configured logger instance
16
+ a configured logger instance
15
17
  """
16
18
  return logging.getLogger(f"FastMCP.{name}")
17
19
 
@@ -22,9 +24,8 @@ def configure_logging(
22
24
  """Configure logging for FastMCP.
23
25
 
24
26
  Args:
25
- level: The log level to use
27
+ level: the log level to use
26
28
  """
27
29
  logging.basicConfig(
28
- level=level,
29
- format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
30
+ level=level, format="%(message)s", handlers=[RichHandler(rich_tracebacks=True)]
30
31
  )
@@ -0,0 +1,53 @@
1
+ """Common types used across FastMCP."""
2
+
3
+ import base64
4
+ from pathlib import Path
5
+ from typing import Optional, Union
6
+
7
+ from mcp.types import ImageContent
8
+
9
+
10
+ class Image:
11
+ """Helper class for returning images from tools."""
12
+
13
+ def __init__(
14
+ self,
15
+ path: Optional[Union[str, Path]] = None,
16
+ data: Optional[bytes] = None,
17
+ format: Optional[str] = None,
18
+ ):
19
+ if path is None and data is None:
20
+ raise ValueError("Either path or data must be provided")
21
+ if path is not None and data is not None:
22
+ raise ValueError("Only one of path or data can be provided")
23
+
24
+ self.path = Path(path) if path else None
25
+ self.data = data
26
+ self._format = format
27
+ self._mime_type = self._get_mime_type()
28
+
29
+ def _get_mime_type(self) -> str:
30
+ """Get MIME type from format or guess from file extension."""
31
+ if self._format:
32
+ return f"image/{self._format.lower()}"
33
+
34
+ if self.path:
35
+ suffix = self.path.suffix.lower()
36
+ return {
37
+ ".png": "image/png",
38
+ ".jpg": "image/jpeg",
39
+ ".jpeg": "image/jpeg",
40
+ ".gif": "image/gif",
41
+ ".webp": "image/webp",
42
+ }.get(suffix, "application/octet-stream")
43
+ return "image/png" # default for raw binary data
44
+
45
+ def to_image_content(self) -> ImageContent:
46
+ """Convert to MCP ImageContent."""
47
+ if self.path:
48
+ with open(self.path, "rb") as f:
49
+ data = base64.b64encode(f.read()).decode()
50
+ else:
51
+ data = base64.b64encode(self.data).decode()
52
+
53
+ return ImageContent(type="image", data=data, mimeType=self._mime_type)
@@ -0,0 +1,407 @@
1
+ Metadata-Version: 2.3
2
+ Name: fastmcp
3
+ Version: 0.3.1
4
+ Summary: A more ergonomic interface for MCP servers
5
+ Author: Jeremiah Lowin
6
+ License: Apache-2.0
7
+ Requires-Python: >=3.10
8
+ Requires-Dist: httpx>=0.26.0
9
+ Requires-Dist: mcp<2.0.0,>=1.0.0
10
+ Requires-Dist: pydantic-settings>=2.6.1
11
+ Requires-Dist: pydantic<3.0.0,>=2.5.3
12
+ Requires-Dist: typer>=0.9.0
13
+ Provides-Extra: dev
14
+ Requires-Dist: copychat>=0.5.2; extra == 'dev'
15
+ Requires-Dist: ipython>=8.12.3; extra == 'dev'
16
+ Requires-Dist: pdbpp>=0.10.3; extra == 'dev'
17
+ Requires-Dist: pre-commit; extra == 'dev'
18
+ Requires-Dist: pytest-asyncio>=0.23.5; extra == 'dev'
19
+ Requires-Dist: pytest-xdist>=3.6.1; extra == 'dev'
20
+ Requires-Dist: pytest>=8.3.3; extra == 'dev'
21
+ Requires-Dist: ruff; extra == 'dev'
22
+ Description-Content-Type: text/markdown
23
+
24
+ <!-- omit in toc -->
25
+ # FastMCP 🚀
26
+
27
+ <div align="center">
28
+
29
+ [![PyPI - Version](https://img.shields.io/pypi/v/fastmcp.svg)](https://pypi.org/project/fastmcp)
30
+ [![Tests](https://github.com/jlowin/fastmcp/actions/workflows/run-tests.yml/badge.svg)](https://github.com/jlowin/fastmcp/actions/workflows/run-tests.yml)
31
+ [![License](https://img.shields.io/github/license/jlowin/fastmcp.svg)](https://github.com/jlowin/fastmcp/blob/main/LICENSE)
32
+
33
+ A fast, Pythonic way to build [Model Context Protocol (MCP)](https://modelcontextprotocol.io) servers
34
+
35
+ </div>
36
+
37
+ FastMCP makes building MCP servers simple and intuitive. Create tools, expose resources, and define prompts with clean, Pythonic code:
38
+
39
+ ```python
40
+ from fastmcp import FastMCP
41
+
42
+ mcp = FastMCP("Demo 🚀")
43
+
44
+ @mcp.tool()
45
+ def add(a: int, b: int) -> int:
46
+ """Add two numbers"""
47
+ return a + b
48
+ ```
49
+
50
+ That's it! FastMCP handles all the complex protocol details and server management, so you can focus on building great tools. It's designed to be high-level and Pythonic - in most cases, decorating a function is all you need.
51
+
52
+
53
+ ### Key features:
54
+ * **Fast**: High-level interface means less code and faster development
55
+ * **Simple**: Build MCP servers with minimal boilerplate
56
+ * **Pythonic**: Feels natural to Python developers
57
+ * **Complete***: FastMCP aims to provide a full implementation of the core MCP specification
58
+
59
+ (\*emphasis on *aims*)
60
+
61
+ 🚨 🚧 🏗️ *FastMCP is under active development, as is the MCP specification itself. Core features are working but some advanced capabilities are still in progress.*
62
+
63
+
64
+ <!-- omit in toc -->
65
+ ## Table of Contents
66
+
67
+ - [Installation](#installation)
68
+ - [Quickstart](#quickstart)
69
+ - [What is MCP?](#what-is-mcp)
70
+ - [Core Concepts](#core-concepts)
71
+ - [Server](#server)
72
+ - [Resources](#resources)
73
+ - [Tools](#tools)
74
+ - [Prompts](#prompts)
75
+ - [Images](#images)
76
+ - [Context](#context)
77
+ - [Deployment](#deployment)
78
+ - [Development](#development)
79
+ - [Claude Desktop](#claude-desktop)
80
+ - [Examples](#examples)
81
+ - [Echo Server](#echo-server)
82
+ - [SQLite Explorer](#sqlite-explorer)
83
+
84
+ ## Installation
85
+
86
+ ```bash
87
+ # We strongly recommend installing with uv
88
+ brew install uv # on macOS
89
+ uv pip install fastmcp
90
+ ```
91
+
92
+ Or with pip:
93
+ ```bash
94
+ pip install fastmcp
95
+ ```
96
+
97
+ ## Quickstart
98
+
99
+ Let's create a simple MCP server that exposes a calculator tool and some data:
100
+
101
+ ```python
102
+ from fastmcp import FastMCP
103
+
104
+
105
+ # Create an MCP server
106
+ mcp = FastMCP("Demo")
107
+
108
+
109
+ # Add an addition tool
110
+ @mcp.tool()
111
+ def add(a: int, b: int) -> int:
112
+ """Add two numbers"""
113
+ return a + b
114
+
115
+
116
+ # Add a dynamic greeting resource
117
+ @mcp.resource("greeting://{name}")
118
+ def get_greeting(name: str) -> str:
119
+ """Get a personalized greeting"""
120
+ return f"Hello, {name}!"
121
+ ```
122
+
123
+ To use this server, you have two options:
124
+
125
+ 1. Install it in [Claude Desktop](https://claude.ai/download):
126
+ ```bash
127
+ fastmcp install server.py
128
+ ```
129
+
130
+ 2. Test it with the MCP Inspector:
131
+ ```bash
132
+ fastmcp dev server.py
133
+ ```
134
+
135
+ ![MCP Inspector](/docs/assets/demo-inspector.png)
136
+
137
+ ## What is MCP?
138
+
139
+ The [Model Context Protocol (MCP)](https://modelcontextprotocol.io) lets you build servers that expose data and functionality to LLM applications in a secure, standardized way. Think of it like a web API, but specifically designed for LLM interactions. MCP servers can:
140
+
141
+ - Expose data through **Resources** (think of these sort of like GET endpoints; they are used to load information into the LLM's context)
142
+ - Provide functionality through **Tools** (sort of like POST endpoints; they are used to execute code or otherwise produce a side effect)
143
+ - Define interaction patterns through **Prompts** (reusable templates for LLM interactions)
144
+ - And more!
145
+
146
+ There is a low-level [Python SDK](https://github.com/modelcontextprotocol/python-sdk) available for implementing the protocol directly, but FastMCP aims to make that easier by providing a high-level, Pythonic interface.
147
+
148
+ ## Core Concepts
149
+
150
+
151
+ ### Server
152
+
153
+ The FastMCP server is your core interface to the MCP protocol. It handles connection management, protocol compliance, and message routing:
154
+
155
+ ```python
156
+ from fastmcp import FastMCP
157
+
158
+ # Create a named server
159
+ mcp = FastMCP("My App")
160
+
161
+ # Configure host/port for HTTP transport (optional)
162
+ mcp = FastMCP("My App", host="localhost", port=8000)
163
+ ```
164
+ *Note: All of the following code examples assume you've created a FastMCP server instance called `mcp`, as shown above.*
165
+
166
+ ### Resources
167
+
168
+ Resources are how you expose data to LLMs. They're similar to GET endpoints in a REST API - they provide data but shouldn't perform significant computation or have side effects. Some examples:
169
+
170
+ - File contents
171
+ - Database schemas
172
+ - API responses
173
+ - System information
174
+
175
+ Resources can be static:
176
+ ```python
177
+ @mcp.resource("config://app")
178
+ def get_config() -> str:
179
+ """Static configuration data"""
180
+ return "App configuration here"
181
+ ```
182
+
183
+ Or dynamic with parameters (FastMCP automatically handles these as MCP templates):
184
+ ```python
185
+ @mcp.resource("users://{user_id}/profile")
186
+ def get_user_profile(user_id: str) -> str:
187
+ """Dynamic user data"""
188
+ return f"Profile data for user {user_id}"
189
+ ```
190
+
191
+ ### Tools
192
+
193
+ Tools let LLMs take actions through your server. Unlike resources, tools are expected to perform computation and have side effects. They're similar to POST endpoints in a REST API.
194
+
195
+ Simple calculation example:
196
+ ```python
197
+ @mcp.tool()
198
+ def calculate_bmi(weight_kg: float, height_m: float) -> float:
199
+ """Calculate BMI given weight in kg and height in meters"""
200
+ return weight_kg / (height_m ** 2)
201
+ ```
202
+
203
+ HTTP request example:
204
+ ```python
205
+ import httpx
206
+
207
+ @mcp.tool()
208
+ async def fetch_weather(city: str) -> str:
209
+ """Fetch current weather for a city"""
210
+ async with httpx.AsyncClient() as client:
211
+ response = await client.get(
212
+ f"https://api.weather.com/{city}"
213
+ )
214
+ return response.text
215
+ ```
216
+
217
+ ### Prompts
218
+
219
+ Prompts are reusable templates that help LLMs interact with your server effectively. They're like "best practices" encoded into your server. A prompt can be as simple as a string:
220
+
221
+ ```python
222
+ @mcp.prompt()
223
+ def review_code(code: str) -> str:
224
+ return f"Please review this code:\n\n{code}"
225
+ ```
226
+
227
+ Or a more structured sequence of messages:
228
+ ```python
229
+ from fastmcp.prompts.base import UserMessage, AssistantMessage
230
+
231
+ @mcp.prompt()
232
+ def debug_error(error: str) -> list[Message]:
233
+ return [
234
+ UserMessage("I'm seeing this error:"),
235
+ UserMessage(error),
236
+ AssistantMessage("I'll help debug that. What have you tried so far?")
237
+ ]
238
+ ```
239
+
240
+
241
+ ### Images
242
+
243
+ FastMCP provides an `Image` class that automatically handles image data in your server:
244
+
245
+ ```python
246
+ from fastmcp import FastMCP, Image
247
+ from PIL import Image as PILImage
248
+
249
+ @mcp.tool()
250
+ def create_thumbnail(image_path: str) -> Image:
251
+ """Create a thumbnail from an image"""
252
+ img = PILImage.open(image_path)
253
+ img.thumbnail((100, 100))
254
+
255
+ # FastMCP automatically handles conversion and MIME types
256
+ return Image(data=img.tobytes(), format="png")
257
+
258
+ @mcp.tool()
259
+ def load_image(path: str) -> Image:
260
+ """Load an image from disk"""
261
+ # FastMCP handles reading and format detection
262
+ return Image(path=path)
263
+ ```
264
+
265
+ Images can be used as the result of both tools and resources.
266
+
267
+ ### Context
268
+
269
+ The Context object gives your tools and resources access to MCP capabilities. To use it, add a parameter annotated with `fastmcp.Context`:
270
+
271
+ ```python
272
+ from fastmcp import FastMCP, Context
273
+
274
+ @mcp.tool()
275
+ async def long_task(files: list[str], ctx: Context) -> str:
276
+ """Process multiple files with progress tracking"""
277
+ for i, file in enumerate(files):
278
+ ctx.info(f"Processing {file}")
279
+ await ctx.report_progress(i, len(files))
280
+
281
+ # Read another resource if needed
282
+ data = await ctx.read_resource(f"file://{file}")
283
+
284
+ return "Processing complete"
285
+ ```
286
+
287
+ The Context object provides:
288
+ - Progress reporting through `report_progress()`
289
+ - Logging via `debug()`, `info()`, `warning()`, and `error()`
290
+ - Resource access through `read_resource()`
291
+ - Request metadata via `request_id` and `client_id`
292
+
293
+ ## Deployment
294
+
295
+ The FastMCP CLI helps you develop and deploy MCP servers.
296
+
297
+ Note that for all deployment commands, you are expected to provide the fully qualified path to your server object. For example, if you have a file `server.py` that contains a FastMCP server named `my_server`, you would provide `path/to/server.py:my_server`.
298
+
299
+ If your server variable has one of the standard names (`mcp`, `server`, or `app`), you can omit the server name from the path and just provide the file: `path/to/server.py`.
300
+
301
+ ### Development
302
+
303
+ Test and debug your server with the MCP Inspector:
304
+ ```bash
305
+ # Provide the fully qualified path to your server
306
+ fastmcp dev server.py:my_mcp_server
307
+
308
+ # Or just the file if your server is named 'mcp', 'server', or 'app'
309
+ fastmcp dev server.py
310
+ ```
311
+
312
+ Your server is run in an isolated environment, so you'll need to indicate any dependencies with the `--with` flag. FastMCP is automatically included. If you are working on a uv project, you can use the `--with-editable` flag to mount your current directory:
313
+
314
+ ```bash
315
+ # With additional packages
316
+ fastmcp dev server.py --with pandas --with numpy
317
+
318
+ # Using your project's dependencies and up-to-date code
319
+ fastmcp dev server.py --with-editable .
320
+ ```
321
+
322
+ ### Claude Desktop
323
+
324
+ Install your server in Claude Desktop:
325
+ ```bash
326
+ # Basic usage (name is taken from your FastMCP instance)
327
+ fastmcp install server.py
328
+
329
+ # With a custom name
330
+ fastmcp install server.py --name "My Server"
331
+
332
+ # With dependencies
333
+ fastmcp install server.py --with pandas --with numpy
334
+
335
+ # Replace an existing server
336
+ fastmcp install server.py --force
337
+ ```
338
+
339
+ The server name in Claude will be:
340
+ 1. The `--name` parameter if provided
341
+ 2. The `name` from your FastMCP instance
342
+ 3. The filename if the server can't be imported
343
+
344
+ ## Examples
345
+
346
+ ### Echo Server
347
+ A simple server demonstrating resources, tools, and prompts:
348
+
349
+ ```python
350
+ from fastmcp import FastMCP
351
+
352
+ mcp = FastMCP("Echo")
353
+
354
+ @mcp.resource("echo://{message}")
355
+ def echo_resource(message: str) -> str:
356
+ """Echo a message as a resource"""
357
+ return f"Resource echo: {message}"
358
+
359
+ @mcp.tool()
360
+ def echo_tool(message: str) -> str:
361
+ """Echo a message as a tool"""
362
+ return f"Tool echo: {message}"
363
+
364
+ @mcp.prompt()
365
+ def echo_prompt(message: str) -> str:
366
+ """Create an echo prompt"""
367
+ return f"Please process this message: {message}"
368
+ ```
369
+
370
+ ### SQLite Explorer
371
+ A more complex example showing database integration:
372
+
373
+ ```python
374
+ from fastmcp import FastMCP
375
+ import sqlite3
376
+
377
+ mcp = FastMCP("SQLite Explorer")
378
+
379
+ @mcp.resource("schema://main")
380
+ def get_schema() -> str:
381
+ """Provide the database schema as a resource"""
382
+ conn = sqlite3.connect("database.db")
383
+ schema = conn.execute(
384
+ "SELECT sql FROM sqlite_master WHERE type='table'"
385
+ ).fetchall()
386
+ return "\n".join(sql[0] for sql in schema if sql[0])
387
+
388
+ @mcp.tool()
389
+ def query_data(sql: str) -> str:
390
+ """Execute SQL queries safely"""
391
+ conn = sqlite3.connect("database.db")
392
+ try:
393
+ result = conn.execute(sql).fetchall()
394
+ return "\n".join(str(row) for row in result)
395
+ except Exception as e:
396
+ return f"Error: {str(e)}"
397
+
398
+ @mcp.prompt()
399
+ def analyze_table(table: str) -> str:
400
+ """Create a prompt template for analyzing tables"""
401
+ return f"""Please analyze this database table:
402
+ Table: {table}
403
+ Schema:
404
+ {get_schema()}
405
+
406
+ What insights can you provide about the structure and relationships?"""
407
+ ```
@@ -0,0 +1,26 @@
1
+ fastmcp/__init__.py,sha256=Y5dHGBwyQPgNP5gzOyNIItefvMZ3vJLdom1oV8A1u_k,248
2
+ fastmcp/exceptions.py,sha256=K0rCgXsUVlws39hz98Tb4BBf_BzIql_zXFZgqbkNTiE,348
3
+ fastmcp/server.py,sha256=JttRzt1bnJGBU8mL4Bo764WHFXQ09QqKc_CUT3390WM,21997
4
+ fastmcp/cli/__init__.py,sha256=7hrwtCHX9nMd9qcz7R_JFSoqbL71fC35cBLXBS430mg,88
5
+ fastmcp/cli/claude.py,sha256=hId0cTmAfCrav72Hg5LeO0SPPNyEVtIOcoKVAy8gD3k,3390
6
+ fastmcp/cli/cli.py,sha256=0r9_HR_wayV5MZARS02ZO1RnRCT8roxdY1CGGYzPNqo,10044
7
+ fastmcp/prompts/__init__.py,sha256=4BsMxoYolpoxg74xkkkzCFL8vvdkLVJ5cIPNs1ND1Jo,99
8
+ fastmcp/prompts/base.py,sha256=WaSsfyFSsUPUbcApkGy3Pm-Ne-Gk-5ZwU3efqRYn1mQ,4996
9
+ fastmcp/prompts/manager.py,sha256=EkexOB_N4QNtC-UlZmIcWcau91ceO2O1K4_kD75pA_A,1485
10
+ fastmcp/prompts/prompt_manager.py,sha256=5uR14gsi7l0YHwbxFH7N5b_ACHHRWyTtBAH3R0-G5rk,1129
11
+ fastmcp/resources/__init__.py,sha256=9QShop6ckX3Khh3BQLZNkB6R2ZhwskAcnh7-sIuX-W8,464
12
+ fastmcp/resources/base.py,sha256=glGLpHp8Eq-LKq7YLJx3LRDiCktLlLaTTmltNcdWzHg,1818
13
+ fastmcp/resources/resource_manager.py,sha256=b0PKpG-pKi7x2Yx-qaeknjv0mqL17zixSIYOz2V5G6o,3271
14
+ fastmcp/resources/templates.py,sha256=EmLlI-ddBBzSTAUiA6-knFnHCE3MPMW2ZoH9WswPKvI,2868
15
+ fastmcp/resources/types.py,sha256=ofE6bfeQQfPSmaWrLGDf3qjCP0kGjKmvupsHDYkSrj0,5658
16
+ fastmcp/tools/__init__.py,sha256=ZboxhyMJDl87Svjov8YwNYwNZi55P9VhmpTjBZLesnk,96
17
+ fastmcp/tools/base.py,sha256=JPdTx8SAl5pKsHyIVxnsLG88f3fbjnopDTOAZ_PoVQE,2585
18
+ fastmcp/tools/tool_manager.py,sha256=PT6XHcQWzhdC6kfdsJaddRn7VLps4nAs5FMG8l1j8Zc,1617
19
+ fastmcp/utilities/__init__.py,sha256=-imJ8S-rXmbXMWeDamldP-dHDqAPg_wwmPVz-LNX14E,31
20
+ fastmcp/utilities/logging.py,sha256=VLJdNc0tIYoQZmpobehLUnWrQz7NXnuwSqrDlFt2RF0,738
21
+ fastmcp/utilities/types.py,sha256=jFlZMZsKrJg4NWc1vTBIILLoHpTVwSd-vxO7ycoRuig,1718
22
+ fastmcp-0.3.1.dist-info/METADATA,sha256=PdOwJThIuqGDpSExh8dUsYyxUQBq0rw5MnOV3an2aTs,12108
23
+ fastmcp-0.3.1.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
24
+ fastmcp-0.3.1.dist-info/entry_points.txt,sha256=ff8bMtKX1JvXyurMibAacMSKbJEPmac9ffAKU9mLnM8,44
25
+ fastmcp-0.3.1.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
26
+ fastmcp-0.3.1.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (75.6.0)
2
+ Generator: hatchling 1.26.3
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-