Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 47 additions & 11 deletions src/mcp_agent/cli/commands/init.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,18 +75,34 @@ def _write_readme(dir_path: Path, content: str, force: bool) -> str | None:
return None


def _write_requirements(dir_path: Path, content: str, force: bool) -> str | None:
"""Create a requirements.txt file with fallback logging if one already exists.

Returns the filename created, or None if it could not be written (in which case
the content is printed to console as a fallback).
"""
path = dir_path / "requirements.txt"
if not path.exists() or force:
ok = _write(path, content, force)
if ok:
return "requirements.txt"
# Fallback: print content to console if we couldn't write the file
console.print(
"\n[yellow]A requirements.txt already exists and could not be overwritten.[/yellow]"
)
console.print("[bold]Suggested requirements.txt contents:[/bold]\n")
console.print(content)
return None


def _copy_pkg_tree(pkg_rel: str, dst: Path, force: bool) -> int:
"""Copy packaged examples from mcp_agent.data/examples/<pkg_rel> into dst.

Uses importlib.resources to locate files installed with the package.
Returns 1 on success, 0 on failure.
"""
try:
root = (
resources.files("mcp_agent.data")
.joinpath("examples")
.joinpath(pkg_rel)
)
root = resources.files("mcp_agent.data").joinpath("examples").joinpath(pkg_rel)
except Exception:
return 0
if not root.exists():
Expand Down Expand Up @@ -116,7 +132,9 @@ def init(
ctx: typer.Context,
dir: Path = typer.Option(Path("."), "--dir", "-d", help="Target directory"),
template: str = typer.Option("basic", "--template", "-t", help="Template to use"),
quickstart: str = typer.Option(None, "--quickstart", help="Quickstart mode: copy example without config files"),
quickstart: str = typer.Option(
None, "--quickstart", help="Quickstart mode: copy example without config files"
),
force: bool = typer.Option(False, "--force", "-f", help="Overwrite existing files"),
no_gitignore: bool = typer.Option(
False, "--no-gitignore", help="Skip creating .gitignore"
Expand Down Expand Up @@ -172,7 +190,10 @@ def init(
"mcp-basic-agent": ("mcp_basic_agent", "basic/mcp_basic_agent"),
"token-counter": ("token_counter", "basic/token_counter"),
"agent-factory": ("agent_factory", "basic/agent_factory"),
"reference-agent-server": ("reference_agent_server", "mcp_agent_server/reference"),
"reference-agent-server": (
"reference_agent_server",
"mcp_agent_server/reference",
),
"elicitation": ("elicitation", "mcp_agent_server/elicitation"),
"sampling": ("sampling", "mcp_agent_server/sampling"),
"notifications": ("notifications", "mcp_agent_server/notifications"),
Expand All @@ -187,7 +208,9 @@ def init(

# Templates table
console.print("[bold cyan]Templates:[/bold cyan]")
console.print("[dim]Creates minimal project structure with config files[/dim]\n")
console.print(
"[dim]Creates minimal project structure with config files[/dim]\n"
)
table1 = Table(show_header=True, header_style="cyan")
table1.add_column("Template", style="green")
table1.add_column("Description")
Expand Down Expand Up @@ -233,7 +256,9 @@ def init(
if copied:
console.print(f"Copied {copied} set(s) to {dst}")
else:
console.print(f"[yellow]Could not copy '{quickstart}' - destination may already exist[/yellow]")
console.print(
f"[yellow]Could not copy '{quickstart}' - destination may already exist[/yellow]"
)
console.print("Use --force to overwrite")

return
Expand Down Expand Up @@ -285,15 +310,19 @@ def init(
copied = _copy_pkg_tree(pkg_rel, dst, force)

if copied:
console.print(f"\n[green]✅ Successfully copied example '{template}'![/green]")
console.print(
f"\n[green]✅ Successfully copied example '{template}'![/green]"
)
console.print(f"Created: [cyan]{dst}[/cyan]\n")
console.print("[bold]Next steps:[/bold]")
console.print(f"1. cd [cyan]{dst}[/cyan]")
console.print("2. Review the README for instructions")
console.print("3. Add your API keys to config/secrets files if needed")
else:
console.print(f"[yellow]Example '{template}' could not be copied[/yellow]")
console.print("The destination may already exist. Use --force to overwrite.")
console.print(
"The destination may already exist. Use --force to overwrite."
)

return

Expand Down Expand Up @@ -337,6 +366,13 @@ def init(
if created:
files_created.append(created)

# Add basic requirements.txt
requirements_content = _load_template("requirements.txt")
if requirements_content:
created = _write_requirements(dir, requirements_content, force)
if created:
files_created.append(created)

elif template == "server":
server_path = dir / "server.py"
server_content = _load_template("basic_agent_server.py")
Expand Down
57 changes: 46 additions & 11 deletions src/mcp_agent/data/templates/README_init.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,9 @@ Welcome! This project was generated by `mcp-agent init`. It’s a minimal, reada

## Quick start

1. Add API keys to `mcp_agent.secrets.yaml` (or set env vars):
1. Add your OpenAI API key to `mcp_agent.secrets.yaml` (or set `OPENAI_API_KEY` env var).

- `OPENAI_API_KEY` (recommended)
- `ANTHROPIC_API_KEY` (optional)
NOTE: You can use another supported provider (e.g. Anthropic) instead, just be sure to set its API key in the `mcp_agent.secrets.yaml` (or set its env var) and import/use the relevant `AugmentedLLM` in `main.py`.

2. Review `mcp_agent.config.yaml`:

Expand All @@ -30,6 +29,7 @@ Welcome! This project was generated by `mcp-agent init`. It’s a minimal, reada
3. Run locally:

```bash
uv pip install -r requirements.txt
uv run main.py
```

Expand All @@ -38,23 +38,58 @@ You’ll see two summaries printed:
- A summary of `README.md` from your current directory.
- A summary of the intro page at modelcontextprotocol.io.

4. Deploy a remote MCP server:

### Run as an MCP server
4. Run locally as an MCP server:

- In `main.py`, UNCOMMENT the server lines that call `create_mcp_server_for_app(agent_app)` and `run_sse_async()`.
- Start the server: `uv run main.py`
- Once you see the server started, e.g.
```bash
Uvicorn running on http://127.0.0.1:8000
```
you can connect to it with your preferred MCP Client. For example, you can use [MCP Inspector](https://github.com/modelcontextprotocol/inspector) to explore and test the server:

```bash
npx @modelcontextprotocol/inspector --transport sse --server-url http://127.0.0.1:8000/sse
```

5. Deploy as a remote MCP server:

When you're ready to deploy, ensure the required API keys are set in `mcp_agent.secrets.yaml` and then run:

```bash
uv run mcp-agent login
```

to authenticate to mcp-agent cloud. You will be redirected to the login page, create an mcp-agent cloud account through Google or Github.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix capitalization: "GitHub" not "Github".

The official name of the platform is "GitHub" with a capital "H".

Apply this diff:

-to authenticate to mcp-agent cloud. You will be redirected to the login page, create an mcp-agent cloud account through Google or Github.
+to authenticate to mcp-agent cloud. You will be redirected to the login page, create an mcp-agent cloud account through Google or GitHub.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
to authenticate to mcp-agent cloud. You will be redirected to the login page, create an mcp-agent cloud account through Google or Github.
to authenticate to mcp-agent cloud. You will be redirected to the login page, create an mcp-agent cloud account through Google or GitHub.
🧰 Tools
🪛 LanguageTool

[uncategorized] ~63-~63: The official name of this software platform is spelled with a capital “H”.
Context: ...p-agent cloud account through Google or Github. Set up your mcp-agent cloud API Key a...

(GITHUB)

🤖 Prompt for AI Agents
In src/mcp_agent/data/templates/README_init.md around line 63, the word "Github"
is incorrectly capitalized; replace it with the correct "GitHub" everywhere in
that line (and similar occurrences if present) so the official product name is
used.


When you're ready to deploy, simply run:
Set up your mcp-agent cloud API Key and copy & paste it into your terminal

```bash
mcp-agent deploy "hello_world"
INFO: Directing to MCP Agent Cloud API login...
Please enter your API key 🔑:
```

- This wraps your app as a hosted MCP SSE server.
- Anything decorated with `@app.tool` (or `@app.async_tool`) runs as a Temporal workflow in the cloud.
In your terminal, deploy the MCP app:

```bash
uv run mcp-agent deploy hello_world
```

You will then be prompted to specify the type of secret to save your OpenAI API key as. Select (1) deployment secret so that it is available to the deployed server.

The `deploy` command will bundle the app files and deploy them, wrapping your app as a hosted MCP SSE server with a URL of the form:
`https://<server_id>.deployments.mcp-agent.com`.

Anything decorated with `@app.tool` (or `@app.async_tool`) runs as a Temporal workflow in the cloud.

Since the mcp-agent app is exposed as an MCP server, it can be used in any MCP client just
like any other MCP server. For example, you can inspect and test the server using MCP Inspector:

```bash
npx @modelcontextprotocol/inspector --transport sse --server-url https://<server_id>.deployments.mcp-agent.com/sse
```

Notes
## Notes

- `app_ctx` is the MCPApp Context (configuration, logger, upstream session, etc.).
- Logging uses `app.logger` and is forwarded as notifications when connected to an MCP client.
Expand Down
12 changes: 9 additions & 3 deletions src/mcp_agent/data/templates/basic_agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
- @app.tool and @app.async_tool decorators to expose your agents as long-running tools on an MCP server.
- Advanced MCP features: Notifications, sampling, and elicitation

You can run this example locally using "uv run main.py", and also deploy it as an MCP server using "mcp-agent deploy".
You can run this example locally using "uv run main.py", and also deploy it as an MCP server using "uv run mcp-agent deploy".

Let's get started!
"""
Expand All @@ -21,7 +21,12 @@
from mcp_agent.agents.agent import Agent
from mcp_agent.agents.agent_spec import AgentSpec
from mcp_agent.core.context import Context as AppContext

# UNCOMMENT to run this MCPApp as a server
# from mcp_agent.server.app_server import create_mcp_server_for_app
from mcp_agent.workflows.factory import create_agent

# We are using the OpenAI augmented LLM for this example but you can swap with others (e.g. AnthropicAugmentedLLM)
from mcp_agent.workflows.llm.augmented_llm_openai import OpenAIAugmentedLLM

# Create the MCPApp, the root of mcp-agent.
Expand Down Expand Up @@ -134,7 +139,8 @@ async def main():
print("Webpage summary:")
print(webpage_summary)

# UNCOMMENT to run this MCPApp as an MCP server
# UNCOMMENT to run this MCPApp as an MCP server (also uncomment the import of create_mcp_server_for_app at the top)
# NOTE: You can comment-out the above agent runs if you only want to run the server
#########################################################
# Create the MCP server that exposes both workflows and agent configurations,
# optionally using custom FastMCP settings
Expand All @@ -148,7 +154,7 @@ async def main():
asyncio.run(main())

# When you're ready to deploy this MCPApp as a remote SSE server, run:
# > mcp-agent deploy "hello_world"
# > uv run mcp-agent deploy "hello_world"
#
# Congrats! You made it to the end of the getting-started example!
# There is a lot more that mcp-agent can do, and we hope you'll explore the rest of the documentation.
Expand Down
5 changes: 5 additions & 0 deletions src/mcp_agent/data/templates/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
mcp-agent

# Optionally, include additional dependencies required for this project
openai
# anthropic
31 changes: 16 additions & 15 deletions src/mcp_agent/data/templates/secrets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,27 @@
# WARNING: Keep this file secure and never commit to version control

# Provider API Keys
# We default to OpenAI, but you can configure your preferred providers here.
# You can also set these as environment variables instead
openai:
api_key: "" # Or use OPENAI_API_KEY env var
api_key: "" # Or remove and use OPENAI_API_KEY env var

anthropic:
api_key: "" # Or use ANTHROPIC_API_KEY env var
# anthropic:
# api_key: "" # Or remove and use ANTHROPIC_API_KEY env var

google:
api_key: "" # Or use GOOGLE_API_KEY env var
# google:
# api_key: "" # Or remove and use GOOGLE_API_KEY env var

azure:
api_key: "" # Or use AZURE_API_KEY env var
base_url: "" # https://your-resource.openai.azure.com/
api_version: "2024-02-01"
# use_default_azure_credential: false # Set to true for DefaultAzureCredential
# azure:
# api_key: "" # Or remove and use AZURE_API_KEY env var
# base_url: "" # https://your-resource.openai.azure.com/
# api_version: "2024-02-01"
# # use_default_azure_credential: false # Set to true for DefaultAzureCredential

bedrock:
aws_access_key_id: "" # Or use AWS_ACCESS_KEY_ID env var
aws_secret_access_key: "" # Or use AWS_SECRET_ACCESS_KEY env var
aws_region: "us-east-1"
# bedrock:
# aws_access_key_id: "" # Or remove and use AWS_ACCESS_KEY_ID env var
# aws_secret_access_key: "" # Or remove and use AWS_SECRET_ACCESS_KEY env var
# aws_region: "us-east-1"

# MCP Server environment variables
# mcp:
Expand All @@ -31,4 +32,4 @@ bedrock:
# GITHUB_PERSONAL_ACCESS_TOKEN: ghp_...
# brave-search:
# env:
# BRAVE_API_KEY: BSA_...
# BRAVE_API_KEY: BSA_...
Loading