fast-agent-mcp 0.2.50__py3-none-any.whl → 0.2.51__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.
Potentially problematic release.
This version of fast-agent-mcp might be problematic. Click here for more details.
- {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/METADATA +1 -1
- {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/RECORD +29 -12
- mcp_agent/cli/commands/quickstart.py +107 -0
- mcp_agent/llm/model_database.py +5 -1
- mcp_agent/llm/model_factory.py +5 -3
- mcp_agent/llm/providers/augmented_llm_openai.py +6 -1
- mcp_agent/llm/providers/augmented_llm_tensorzero_openai.py +127 -0
- mcp_agent/llm/providers/google_converter.py +4 -0
- mcp_agent/resources/examples/tensorzero/.env.sample +2 -0
- mcp_agent/resources/examples/tensorzero/Makefile +31 -0
- mcp_agent/resources/examples/tensorzero/README.md +55 -0
- mcp_agent/resources/examples/tensorzero/agent.py +35 -0
- mcp_agent/resources/examples/tensorzero/demo_images/clam.jpg +0 -0
- mcp_agent/resources/examples/tensorzero/demo_images/crab.png +0 -0
- mcp_agent/resources/examples/tensorzero/demo_images/shrimp.png +0 -0
- mcp_agent/resources/examples/tensorzero/docker-compose.yml +105 -0
- mcp_agent/resources/examples/tensorzero/fastagent.config.yaml +19 -0
- mcp_agent/resources/examples/tensorzero/image_demo.py +67 -0
- mcp_agent/resources/examples/tensorzero/mcp_server/Dockerfile +25 -0
- mcp_agent/resources/examples/tensorzero/mcp_server/entrypoint.sh +35 -0
- mcp_agent/resources/examples/tensorzero/mcp_server/mcp_server.py +31 -0
- mcp_agent/resources/examples/tensorzero/mcp_server/pyproject.toml +11 -0
- mcp_agent/resources/examples/tensorzero/simple_agent.py +25 -0
- mcp_agent/resources/examples/tensorzero/tensorzero_config/system_schema.json +29 -0
- mcp_agent/resources/examples/tensorzero/tensorzero_config/system_template.minijinja +11 -0
- mcp_agent/resources/examples/tensorzero/tensorzero_config/tensorzero.toml +35 -0
- mcp_agent/llm/providers/augmented_llm_tensorzero.py +0 -441
- mcp_agent/llm/providers/multipart_converter_tensorzero.py +0 -201
- {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/WHEEL +0 -0
- {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/entry_points.txt +0 -0
- {fast_agent_mcp-0.2.50.dist-info → fast_agent_mcp-0.2.51.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
# This is a simplified example for learning purposes. Do not use this in production.
|
|
2
|
+
# For production-ready deployments, see: https://www.tensorzero.com/docs/gateway/deployment
|
|
3
|
+
|
|
4
|
+
# Top-level volumes definition
|
|
5
|
+
volumes:
|
|
6
|
+
minio_data: {}
|
|
7
|
+
|
|
8
|
+
services:
|
|
9
|
+
clickhouse:
|
|
10
|
+
image: clickhouse/clickhouse-server:24.12-alpine
|
|
11
|
+
environment:
|
|
12
|
+
CLICKHOUSE_USER: chuser
|
|
13
|
+
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: 1
|
|
14
|
+
CLICKHOUSE_PASSWORD: chpassword
|
|
15
|
+
ports:
|
|
16
|
+
- "8123:8123"
|
|
17
|
+
healthcheck:
|
|
18
|
+
test: wget --spider --tries 1 http://chuser:chpassword@clickhouse:8123/ping
|
|
19
|
+
start_period: 30s
|
|
20
|
+
start_interval: 1s
|
|
21
|
+
timeout: 1s
|
|
22
|
+
|
|
23
|
+
gateway:
|
|
24
|
+
image: tensorzero/gateway
|
|
25
|
+
volumes:
|
|
26
|
+
- ./tensorzero_config:/app/config:ro
|
|
27
|
+
env_file:
|
|
28
|
+
- ./.env
|
|
29
|
+
command: --config-file /app/config/tensorzero.toml
|
|
30
|
+
environment: # WARNING: Insecure default credentials for local testing ONLY. Don't send this to production.
|
|
31
|
+
TENSORZERO_CLICKHOUSE_URL: http://chuser:chpassword@clickhouse:8123/tensorzero
|
|
32
|
+
S3_ACCESS_KEY_ID: user
|
|
33
|
+
S3_SECRET_ACCESS_KEY: password
|
|
34
|
+
ports:
|
|
35
|
+
- "3000:3000"
|
|
36
|
+
extra_hosts:
|
|
37
|
+
- "host.docker.internal:host-gateway"
|
|
38
|
+
depends_on:
|
|
39
|
+
clickhouse:
|
|
40
|
+
condition: service_healthy
|
|
41
|
+
minio:
|
|
42
|
+
condition: service_healthy
|
|
43
|
+
mcp-server:
|
|
44
|
+
condition: service_healthy
|
|
45
|
+
|
|
46
|
+
gateway-ui:
|
|
47
|
+
image: tensorzero/ui
|
|
48
|
+
volumes:
|
|
49
|
+
- ./tensorzero_config:/app/config:ro
|
|
50
|
+
env_file:
|
|
51
|
+
- ./.env
|
|
52
|
+
command: --config-file /app/config/tensorzero.toml
|
|
53
|
+
environment:
|
|
54
|
+
TENSORZERO_CLICKHOUSE_URL: http://chuser:chpassword@clickhouse:8123/tensorzero
|
|
55
|
+
TENSORZERO_GATEWAY_URL: http://gateway:3000
|
|
56
|
+
S3_ACCESS_KEY_ID: user
|
|
57
|
+
S3_SECRET_ACCESS_KEY: password
|
|
58
|
+
ports:
|
|
59
|
+
- "4000:4000"
|
|
60
|
+
depends_on:
|
|
61
|
+
clickhouse:
|
|
62
|
+
condition: service_healthy
|
|
63
|
+
|
|
64
|
+
mcp-server:
|
|
65
|
+
build:
|
|
66
|
+
context: ./mcp_server
|
|
67
|
+
dockerfile: Dockerfile
|
|
68
|
+
working_dir: /app
|
|
69
|
+
volumes:
|
|
70
|
+
- ./mcp_server:/app
|
|
71
|
+
ports:
|
|
72
|
+
- "8000:8000"
|
|
73
|
+
depends_on:
|
|
74
|
+
minio:
|
|
75
|
+
condition: service_healthy
|
|
76
|
+
healthcheck:
|
|
77
|
+
test:
|
|
78
|
+
[
|
|
79
|
+
"CMD",
|
|
80
|
+
"wget",
|
|
81
|
+
"--spider",
|
|
82
|
+
"--tries=1",
|
|
83
|
+
"http://localhost:8000/t0-example-server/sse",
|
|
84
|
+
]
|
|
85
|
+
interval: 10s
|
|
86
|
+
timeout: 5s
|
|
87
|
+
retries: 12
|
|
88
|
+
start_period: 20s
|
|
89
|
+
|
|
90
|
+
minio:
|
|
91
|
+
image: minio/minio:latest
|
|
92
|
+
ports:
|
|
93
|
+
- "9000:9000" # API port
|
|
94
|
+
- "9001:9001" # Console port
|
|
95
|
+
volumes:
|
|
96
|
+
- minio_data:/data
|
|
97
|
+
environment: # WARNING: Insecure default credentials for local testing ONLY.
|
|
98
|
+
MINIO_ROOT_USER: user
|
|
99
|
+
MINIO_ROOT_PASSWORD: password
|
|
100
|
+
command: server /data --console-address :9001
|
|
101
|
+
healthcheck:
|
|
102
|
+
test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
|
|
103
|
+
interval: 30s
|
|
104
|
+
timeout: 20s
|
|
105
|
+
retries: 3
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
default_model: haiku
|
|
2
|
+
|
|
3
|
+
tensorzero:
|
|
4
|
+
base_url: http://localhost:3000
|
|
5
|
+
api_key: verysecret
|
|
6
|
+
|
|
7
|
+
logger:
|
|
8
|
+
level: "info"
|
|
9
|
+
progress_display: true
|
|
10
|
+
show_chat: true
|
|
11
|
+
show_tools: true
|
|
12
|
+
truncate_tools: true
|
|
13
|
+
|
|
14
|
+
mcp:
|
|
15
|
+
servers:
|
|
16
|
+
tester:
|
|
17
|
+
transport: "sse"
|
|
18
|
+
url: "http://localhost:8000/t0-example-server/sse"
|
|
19
|
+
read_transport_sse_timeout_seconds: 300
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
import base64
|
|
3
|
+
import mimetypes
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import List, Union
|
|
6
|
+
|
|
7
|
+
from mcp.types import ImageContent, TextContent
|
|
8
|
+
|
|
9
|
+
from mcp_agent.core.fastagent import FastAgent
|
|
10
|
+
from mcp_agent.core.prompt import Prompt
|
|
11
|
+
from mcp_agent.core.request_params import RequestParams
|
|
12
|
+
|
|
13
|
+
AGENT_NAME = "tensorzero_image_tester"
|
|
14
|
+
TENSORZERO_MODEL = "tensorzero.test_chat"
|
|
15
|
+
TEXT_PROMPT = (
|
|
16
|
+
"Provide a description of the similarities and differences between these three images."
|
|
17
|
+
)
|
|
18
|
+
LOCAL_IMAGE_FILES = [
|
|
19
|
+
Path("./demo_images/clam.jpg"),
|
|
20
|
+
Path("./demo_images/shrimp.png"),
|
|
21
|
+
Path("./demo_images/crab.png"),
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
MY_T0_SYSTEM_VARS = {
|
|
25
|
+
"TEST_VARIABLE_1": "Roses are red",
|
|
26
|
+
"TEST_VARIABLE_2": "Violets are blue",
|
|
27
|
+
"TEST_VARIABLE_3": "Sugar is sweet",
|
|
28
|
+
"TEST_VARIABLE_4": "Vibe code responsibly 👍",
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
fast = FastAgent("TensorZero Image Demo - Base64 Only")
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@fast.agent(
|
|
35
|
+
name=AGENT_NAME,
|
|
36
|
+
model=TENSORZERO_MODEL,
|
|
37
|
+
request_params=RequestParams(template_vars=MY_T0_SYSTEM_VARS),
|
|
38
|
+
)
|
|
39
|
+
async def main():
|
|
40
|
+
content_parts: List[Union[TextContent, ImageContent]] = []
|
|
41
|
+
content_parts.append(TextContent(type="text", text=TEXT_PROMPT))
|
|
42
|
+
|
|
43
|
+
for file_path in LOCAL_IMAGE_FILES:
|
|
44
|
+
mime_type, _ = mimetypes.guess_type(file_path)
|
|
45
|
+
if not mime_type or not mime_type.startswith("image/"):
|
|
46
|
+
ext = file_path.suffix.lower()
|
|
47
|
+
if ext == ".jpg" or ext == ".jpeg":
|
|
48
|
+
mime_type = "image/jpeg"
|
|
49
|
+
elif ext == ".png":
|
|
50
|
+
mime_type = "image/png"
|
|
51
|
+
if mime_type is None:
|
|
52
|
+
mime_type = "image/png" # Default fallback if still None
|
|
53
|
+
|
|
54
|
+
with open(file_path, "rb") as image_file:
|
|
55
|
+
image_bytes = image_file.read()
|
|
56
|
+
|
|
57
|
+
encoded_data = base64.b64encode(image_bytes).decode("utf-8")
|
|
58
|
+
content_parts.append(ImageContent(type="image", mimeType=mime_type, data=encoded_data))
|
|
59
|
+
|
|
60
|
+
message = Prompt.user(*content_parts)
|
|
61
|
+
async with fast.run() as agent_app:
|
|
62
|
+
agent = getattr(agent_app, AGENT_NAME)
|
|
63
|
+
await agent.send(message)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
if __name__ == "__main__":
|
|
67
|
+
asyncio.run(main()) # type: ignore
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
WORKDIR /app
|
|
3
|
+
|
|
4
|
+
RUN apt-get update && apt-get install -y curl wget && \
|
|
5
|
+
wget https://dl.min.io/client/mc/release/linux-amd64/mc -O /usr/local/bin/mc && \
|
|
6
|
+
chmod +x /usr/local/bin/mc && \
|
|
7
|
+
apt-get clean && rm -rf /var/lib/apt/lists/*
|
|
8
|
+
|
|
9
|
+
RUN pip install uv
|
|
10
|
+
|
|
11
|
+
# Copy dependency files only
|
|
12
|
+
COPY pyproject.toml /tmp/
|
|
13
|
+
#COPY uv.lock /tmp/
|
|
14
|
+
|
|
15
|
+
# Install dependencies
|
|
16
|
+
WORKDIR /tmp
|
|
17
|
+
RUN uv pip install --system .
|
|
18
|
+
|
|
19
|
+
# Switch back to /app (this will be overridden by volume mount)
|
|
20
|
+
WORKDIR /app
|
|
21
|
+
|
|
22
|
+
# These files will come from the volume mount at runtime
|
|
23
|
+
EXPOSE 8000
|
|
24
|
+
ENTRYPOINT ["/app/entrypoint.sh"]
|
|
25
|
+
CMD ["uvicorn", "mcp_server:app", "--host", "0.0.0.0", "--port", "8000"]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/bin/sh
|
|
2
|
+
|
|
3
|
+
echo "Entrypoint: Waiting for MinIO to be healthy..."
|
|
4
|
+
|
|
5
|
+
# Simple loop to check MinIO health endpoint (within the Docker network)
|
|
6
|
+
# Adjust timeout as needed
|
|
7
|
+
TIMEOUT=60
|
|
8
|
+
START_TIME=$(date +%s)
|
|
9
|
+
while ! curl -sf http://minio:9000/minio/health/live > /dev/null; do
|
|
10
|
+
CURRENT_TIME=$(date +%s)
|
|
11
|
+
ELAPSED=$(($CURRENT_TIME - $START_TIME))
|
|
12
|
+
if [ $ELAPSED -ge $TIMEOUT ]; then
|
|
13
|
+
echo "Entrypoint: Timeout waiting for MinIO!"
|
|
14
|
+
exit 1
|
|
15
|
+
fi
|
|
16
|
+
echo "Entrypoint: MinIO not ready, sleeping..."
|
|
17
|
+
sleep 2
|
|
18
|
+
done
|
|
19
|
+
echo "Entrypoint: MinIO is healthy."
|
|
20
|
+
|
|
21
|
+
echo "Entrypoint: Configuring mc client and creating bucket 'tensorzero'..."
|
|
22
|
+
|
|
23
|
+
# Configure mc to talk to the MinIO server using the service name
|
|
24
|
+
# Use --insecure because we are using http
|
|
25
|
+
mc --insecure alias set local http://minio:9000 user password
|
|
26
|
+
|
|
27
|
+
# Create the bucket if it doesn't exist
|
|
28
|
+
# Use --insecure because we are using http
|
|
29
|
+
mc --insecure ls local/tensorzero > /dev/null 2>&1 || mc --insecure mb local/tensorzero
|
|
30
|
+
|
|
31
|
+
echo "Entrypoint: Bucket 'tensorzero' check/creation complete."
|
|
32
|
+
|
|
33
|
+
echo "Entrypoint: Executing the main container command: $@"
|
|
34
|
+
|
|
35
|
+
exec "$@"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import uvicorn
|
|
2
|
+
from mcp.server.fastmcp.server import FastMCP
|
|
3
|
+
from starlette.applications import Starlette
|
|
4
|
+
from starlette.routing import Mount
|
|
5
|
+
|
|
6
|
+
SERVER_PATH = "t0-example-server"
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
mcp_instance = FastMCP(name="t0-example-server")
|
|
10
|
+
mcp_instance.settings.message_path = f"/{SERVER_PATH}/messages/"
|
|
11
|
+
mcp_instance.settings.sse_path = f"/{SERVER_PATH}/sse"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@mcp_instance.tool()
|
|
15
|
+
def example_tool(input_text: str) -> str:
|
|
16
|
+
"""Example tool that reverses the text of a given string."""
|
|
17
|
+
reversed_text = input_text[::-1]
|
|
18
|
+
return reversed_text
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
app = Starlette(
|
|
22
|
+
routes=[
|
|
23
|
+
Mount("/", app=mcp_instance.sse_app()),
|
|
24
|
+
]
|
|
25
|
+
)
|
|
26
|
+
|
|
27
|
+
if __name__ == "__main__":
|
|
28
|
+
print(f"Starting minimal MCP server ({mcp_instance.name}) on http://127.0.0.1:8000")
|
|
29
|
+
print(f" -> SSE endpoint: {mcp_instance.settings.sse_path}")
|
|
30
|
+
print(f" -> Message endpoint: {mcp_instance.settings.message_path}")
|
|
31
|
+
uvicorn.run(app, host="127.0.0.1", port=8000)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import asyncio
|
|
2
|
+
|
|
3
|
+
from mcp_agent.core.fastagent import FastAgent
|
|
4
|
+
|
|
5
|
+
CONFIG_FILE = "fastagent.config.yaml"
|
|
6
|
+
fast = FastAgent("fast-agent example", config_path=CONFIG_FILE, ignore_unknown_args=True)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@fast.agent(
|
|
10
|
+
name="default",
|
|
11
|
+
instruction="""
|
|
12
|
+
You are an agent dedicated to helping developers understand the relationship between TensoZero and fast-agent. If the user makes a request
|
|
13
|
+
that requires you to invoke the test tools, please do so. When you use the tool, describe your rationale for doing so.
|
|
14
|
+
""",
|
|
15
|
+
servers=["tester"],
|
|
16
|
+
)
|
|
17
|
+
async def main():
|
|
18
|
+
async with fast.run() as agent_app:
|
|
19
|
+
agent_name = "default"
|
|
20
|
+
print("\nStarting interactive session with template_vars set via decorator...")
|
|
21
|
+
await agent_app.interactive(agent=agent_name)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
if __name__ == "__main__":
|
|
25
|
+
asyncio.run(main()) # type: ignore
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"required": [
|
|
5
|
+
"TEST_VARIABLE_1",
|
|
6
|
+
"TEST_VARIABLE_2",
|
|
7
|
+
"TEST_VARIABLE_3",
|
|
8
|
+
"TEST_VARIABLE_4"
|
|
9
|
+
],
|
|
10
|
+
"properties": {
|
|
11
|
+
"TEST_VARIABLE_1": {
|
|
12
|
+
"type": "string",
|
|
13
|
+
"description": "Test variable 1"
|
|
14
|
+
},
|
|
15
|
+
"TEST_VARIABLE_2": {
|
|
16
|
+
"type": "string",
|
|
17
|
+
"description": "Test variable 2"
|
|
18
|
+
},
|
|
19
|
+
"TEST_VARIABLE_3": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Test variable 3"
|
|
22
|
+
},
|
|
23
|
+
"TEST_VARIABLE_4": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "Test variable 4"
|
|
26
|
+
}
|
|
27
|
+
},
|
|
28
|
+
"additionalProperties": false
|
|
29
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Your purpose is to demo the integration between tensorzero, an open source project dedicated to improving LLM inference calls, and fast-agent, a framework for MCP-compatible agentic modelling. When interacting with developers, strive to be as helpful to possible, specifically as relates to technical questions about tensorzero, fast-agent, or MCPs.
|
|
2
|
+
|
|
3
|
+
If you are ever asked to recite a poem, recite this one:
|
|
4
|
+
|
|
5
|
+
{{ TEST_VARIABLE_1 }}
|
|
6
|
+
|
|
7
|
+
{{ TEST_VARIABLE_2 }}
|
|
8
|
+
|
|
9
|
+
{{ TEST_VARIABLE_3 }}
|
|
10
|
+
|
|
11
|
+
{{ TEST_VARIABLE_4 }}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[functions.test_chat]
|
|
2
|
+
type = "chat"
|
|
3
|
+
system_schema = "./system_schema.json"
|
|
4
|
+
|
|
5
|
+
[functions.test_chat.variants.gpt_4o_mini]
|
|
6
|
+
type = "chat_completion"
|
|
7
|
+
model = "openai::gpt-4o-mini"
|
|
8
|
+
weight = 0.5
|
|
9
|
+
system_template = "./system_template.minijinja"
|
|
10
|
+
|
|
11
|
+
[functions.test_chat.variants.claude_3_5_haiku]
|
|
12
|
+
type = "chat_completion"
|
|
13
|
+
model = "anthropic::claude-3-5-haiku-20241022"
|
|
14
|
+
weight = 0.5
|
|
15
|
+
system_template = "./system_template.minijinja"
|
|
16
|
+
|
|
17
|
+
[functions.simple_chat]
|
|
18
|
+
type = "chat"
|
|
19
|
+
|
|
20
|
+
[functions.simple_chat.variants.gpt_4o_mini]
|
|
21
|
+
type = "chat_completion"
|
|
22
|
+
model = "openai::gpt-4o-mini"
|
|
23
|
+
weight = 0.5
|
|
24
|
+
|
|
25
|
+
[functions.simple_chat.variants.claude_3_5_haiku]
|
|
26
|
+
type = "chat_completion"
|
|
27
|
+
model = "anthropic::claude-3-5-haiku-20241022"
|
|
28
|
+
weight = 0.5
|
|
29
|
+
|
|
30
|
+
# Object Storage Configuration for MinIO, simulating AWS S3 bucket
|
|
31
|
+
[object_storage]
|
|
32
|
+
type = "s3_compatible"
|
|
33
|
+
endpoint = "http://minio:9000"
|
|
34
|
+
bucket_name = "tensorzero"
|
|
35
|
+
allow_http = true
|