Skip to content

Commit 44a9367

Browse files
mconflitti-pbcdotNomadnealrichardson
authored
Simple MCP Server + Shiny Chat with MCP Support (#179)
* Initial version of simple mcp server with companion simple shiny chat app * fixed error pertaining to unpacking from transport * Add .gitignore and update manifest files for simple MCP server and shiny chat app - Created .gitignore files for both simple MCP server and shiny chat app to exclude environment files. - Enhanced manifest.json for simple MCP server with metadata and versioning details. - Added manifest.json for simple shiny chat app with relevant metadata and dependencies. - Refactored main.py and app.py for improved readability and consistency. - Updated requirements.txt and pyproject.toml to include new dependencies. * Fix MCP client and chat app using asyncio support for tool registration and cleanup * Update .gitignore files and modify MCP endpoint to remove connect api tool until we have ability to use multiple integrations per app * add example category to these extensions * add required features * Add simple MCP server and shiny chat extensions with updated manifests to the github workflow * add tags to extensions.json * use jinja ext; widen supported python versions * pr feedback * updated look and feel; added setup screen for Chatlas and Visitor API key integration requirements * Add Simple MCP Server and Shiny Chat extensions with updated documentation and requirements - Added demo images for both Simple MCP Server and Simple Shiny Chat. - Updated README files to include detailed usage instructions and features. - Modified pyproject.toml and requirements.txt to reflect new dependencies and Python version requirements. - Removed unused MCP client code from Simple Shiny Chat in favor of Chatlas features * rename shiny chat to include mcp; adding contributing doc * Update extensions/simple-shiny-chat-with-mcp/manifest.json Co-authored-by: Jordan Jensen <[email protected]> * Add AWS Bedrock credentials check and update chat initialization logic; fix mcp delete-then-add issue. * Update README and index.html to include recommendation for minimum instances in content settings * lint fix * Update extensions/simple-mcp-server/README.md Co-authored-by: Neal Richardson <[email protected]> * updated readmes --------- Co-authored-by: Jordan Jensen <[email protected]> Co-authored-by: Neal Richardson <[email protected]>
1 parent fea924d commit 44a9367

File tree

20 files changed

+1315
-2
lines changed

20 files changed

+1315
-2
lines changed

.github/workflows/extensions.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,8 @@ jobs:
5656
app-canary: extensions/app-canary/**
5757
voila-example: extensions/voila-example/**
5858
stock-report: extensions/stock-report/**
59+
simple-mcp-server: extensions/simple-mcp-server/**
60+
simple-shiny-chat-with-mcp: extensions/simple-shiny-chat-with-mcp/**
5961
6062
# Runs for each extension that has changed from `simple-extension-changes`
6163
# Lints and packages in preparation for tests and and release.

extensions.json

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,13 @@
1111
"description": "Pre-built content to illustrate the types of content publishable on Posit Connect."
1212
}
1313
],
14-
"tags": [],
14+
"tags": [
15+
"python",
16+
"shiny",
17+
"fastapi",
18+
"mcp",
19+
"llm"
20+
],
1521
"requiredFeatures": [
1622
"API Publishing",
1723
"OAuth Integrations",
@@ -1094,4 +1100,4 @@
10941100
"category": "example"
10951101
}
10961102
]
1097-
}
1103+
}
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.venv
2+
.env
3+
rsconnect-python
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
3.11
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
# Contributing to the Simple MCP Server Extension
2+
3+
## Local Development
4+
5+
For local testing and development:
6+
7+
```bash
8+
# Install dependencies
9+
pip install -r requirements.txt
10+
11+
# Run the server locally
12+
python main.py
13+
```
14+
15+
The server will start on `http://127.0.0.1:8001` with the MCP endpoint at `/mcp`.
16+
17+
## Tool Development
18+
19+
### Adding New Tools
20+
21+
To add new MCP tools, use the `@mcp.tool()` decorator:
22+
23+
```python
24+
@mcp.tool()
25+
def your_new_tool(parameter: str) -> str:
26+
"""
27+
Description of what your tool does.
28+
29+
Args:
30+
parameter: Description of the parameter
31+
32+
Returns:
33+
Description of the return value
34+
"""
35+
# Your tool implementation
36+
return "result"
37+
```
38+
39+
### Error Handling
40+
41+
Use `ToolError` for proper error handling:
42+
43+
```python
44+
from mcp.server.fastmcp.exceptions import ToolError
45+
46+
@mcp.tool()
47+
def example_tool(input_value: str) -> str:
48+
if not input_value:
49+
raise ToolError("Input value cannot be empty")
50+
return f"Processed: {input_value}"
51+
```
52+
53+
## Authentication
54+
55+
The server supports Connect API key authentication for tools that interact with Connect services. API keys should be passed in the `x-mcp-authorization` header in the format:
56+
57+
```
58+
x-mcp-authorization: Key YOUR_API_KEY
59+
```
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
# Simple MCP Server
2+
3+
A FastAPI-based Model Context Protocol (MCP) server that demonstrates how to deploy MCP tools on Posit Connect. This extension showcases Connect's ability to host MCP servers that can be consumed by AI assistants and other MCP clients.
4+
5+
## Overview
6+
7+
This extension demonstrates Connect's capability to host Model Context Protocol servers, enabling LLMs to access and execute tools remotely. The Simple MCP Server provides a collection of data analysis tools and Connect integration capabilities, making it an ideal companion for AI-powered applications like the [Simple Shiny Chat](../simple-shiny-chat-with-mcp/README.md) extension.
8+
9+
![MCP Server Landing Page](./images/demo.png)
10+
11+
## Features
12+
13+
- **FastAPI-Based MCP Server**: Built on FastAPI with streamable HTTP transport for efficient MCP communication
14+
- **Data Analysis Tools**: Includes tools for dataset operations and summary statistics
15+
- **Connect Integration**: Provides tools that interact with Connect's API
16+
- **Interactive Documentation**: Clean web interface that displays available tools and their parameters
17+
- **Copy-to-Clipboard Endpoint**: Easy sharing of MCP server URLs
18+
- **Automatic Tool Discovery**: MCP clients can dynamically discover and use available tools
19+
20+
## Available Tools
21+
22+
### Dataset Operations
23+
- **`list_known_datasets`**: Lists all available datasets in the server
24+
- **`calculate_summary_statistics`**: Generates comprehensive summary statistics for specified datasets
25+
26+
### Connect Integration
27+
- **`connect_whoami`**: Calls the Connect `/me` endpoint using API key authentication
28+
29+
### Sample Datasets
30+
- **Iris Dataset**: Classic machine learning dataset from scikit-learn
31+
- **Sample Data**: Simple demonstration dataset with mixed data types
32+
33+
## Prerequisites
34+
35+
### Connect Requirements
36+
37+
1. **Minimum Connect Version**: 2025.04.0 or later
38+
2. **API Publishing**: Must be enabled on your Connect server
39+
3. **Python 3.10+**: Required for the MCP SDK
40+
41+
## Deployment
42+
43+
### 1. Deploy the Extension
44+
Deploy this extension to your Connect server. If you are deploying through the Connect Gallery, see the [Gallery documentation](https://docs.posit.co/connect/user/publishing-connect-gallery/).
45+
46+
### 2. Access the Server
47+
Once deployed, the extension provides:
48+
- **Web Interface**: Visit the content URL to see available tools and copy the MCP endpoint
49+
- **MCP Endpoint**: Located at `{direct-content-url}/mcp` for MCP client connections
50+
51+
Please note that it is recommended to set the minimum number of instances/processes for this application to >= 1 in the content settings. This will ensure that the MCP server is always available for clients to connect. See the [content process configuration documentation](https://docs.posit.co/connect/user/content-settings/index.html#process-configurations).
52+
53+
### 3. Use with MCP Clients
54+
The server can be consumed by any MCP-compatible client, including:
55+
- [Simple Shiny Chat](../simple-shiny-chat-with-mcp/README.md) extension
56+
- Local MCP clients
57+
- AI development environments that support MCP
58+
59+
## Usage Examples
60+
61+
### With Simple Shiny Chat Extension
62+
63+
1. Deploy both the Simple MCP Server and Simple Shiny Chat extensions
64+
2. In the chat application, add the MCP server URL from this extension
65+
3. Ask the AI assistant to:
66+
- "What datasets are available?"
67+
- "Calculate summary statistics for the iris dataset"
68+
- "Show me information about my Connect user account"
69+
70+
### With Other MCP Clients
71+
72+
Connect to the MCP endpoint at `{your-connect-server}/content/{content-guid}/mcp` and use the available tools programmatically.
73+
74+
If you are not using the Simple Shiny Chat extension to connect to this MCP server, you will need to ensure that you can specify your Connect API key in both the `x-mcp-authorization` header and the `authorization` header for Connect API calls. Some MCP clients may not support that directly today (June 2025).
75+
76+
## Architecture
77+
78+
The application consists of several key components:
79+
80+
- **FastMCP Framework**: Handles MCP protocol implementation and tool registration
81+
- **FastAPI Application**: Provides HTTP transport and web interface
82+
- **Tool Implementations**: Individual functions that implement business logic
83+
- **Template Engine**: Jinja2 templates for the documentation interface
84+
- **Dataset Storage**: In-memory storage for demonstration datasets
85+
86+
## Troubleshooting
87+
88+
### Deployment Issues
89+
- Ensure your Connect server supports API publishing
90+
- Verify Python 3.10+ is available in your Connect environment
91+
- Check that all dependencies are properly installed
92+
93+
### MCP Client Connection Issues
94+
- Verify the MCP endpoint URL is correct (`{content-url}/mcp`)
95+
- Ensure the server is accessible from the client
96+
- Check Connect content permissions
97+
98+
### Tool Execution Errors
99+
- Review tool parameter requirements and types
100+
- Verify API key format for Connect integration tools
101+
- Check Connect logs for detailed error messages
102+
103+
## Integration with Simple Shiny Chat
104+
105+
This MCP server is designed to work seamlessly with the [Simple Shiny Chat](../simple-shiny-chat-with-mcp/README.md) extension:
106+
107+
1. Deploy both extensions to your Connect server
108+
2. Configure the chat application with appropriate LLM credentials
109+
3. Register this MCP server in the chat interface
110+
4. Start conversing with AI assistants that can use these tools
111+
112+
## Related Resources
113+
114+
- [Model Context Protocol Documentation](https://modelcontextprotocol.io/)
115+
- [FastMCP Framework](https://github.com/jlowin/fastmcp)
116+
- [MCP Framework](https://github.com/modelcontextprotocol/python-sdk)
117+
- [FastAPI Documentation](https://fastapi.tiangolo.com/)
118+
- [Simple Shiny Chat Extension](../simple-shiny-chat-with-mcp/README.md)
119+
- [Posit Connect Extension Gallery Guide](https://docs.posit.co/connect/admin/connect-gallery/index.html)
120+
121+
## Support
122+
123+
For issues specific to this extension, please check the [Connect Extensions repository](https://github.com/posit-dev/connect-extensions).
116 KB
Loading
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>{{ server_name }}</title>
7+
<style>
8+
body {
9+
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
10+
line-height: 1.6;
11+
margin: 0;
12+
padding: 20px;
13+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
14+
color: #333;
15+
height: 100vh;
16+
}
17+
.container {
18+
max-width: 800px;
19+
margin: 0 auto;
20+
background-color: #fff;
21+
padding: 30px;
22+
border-radius: 8px;
23+
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
24+
}
25+
h1 {
26+
color: #2c3e50;
27+
margin-top: 0;
28+
}
29+
h2 {
30+
color: #34495e;
31+
border-bottom: 2px solid #ecf0f1;
32+
padding-bottom: 10px;
33+
margin-top: 30px;
34+
}
35+
p {
36+
margin-bottom: 15px;
37+
}
38+
strong {
39+
color: #2980b9;
40+
}
41+
ul {
42+
list-style-type: none;
43+
padding-left: 0;
44+
}
45+
li {
46+
background-color: #f9f9f9;
47+
border: 1px solid #eee;
48+
padding: 15px;
49+
margin-bottom: 10px;
50+
border-radius: 4px;
51+
}
52+
li strong {
53+
color: #34495e;
54+
}
55+
.tool-parameters {
56+
font-size: 0.9em;
57+
color: #555;
58+
margin-top: 8px;
59+
padding-left: 15px;
60+
border-left: 2px solid #ddd;
61+
}
62+
.tool-parameters p {
63+
margin: 5px 0;
64+
}
65+
.tool-parameters code {
66+
background-color: #e9ecef;
67+
padding: 2px 4px;
68+
border-radius: 3px;
69+
font-family: "Courier New", Courier, monospace;
70+
}
71+
.mcp-endpoint-section {
72+
display: flex;
73+
align-items: center;
74+
gap: 10px;
75+
margin-bottom: 20px;
76+
}
77+
#mcpEndpointUrl {
78+
flex-grow: 1;
79+
padding: 8px 12px;
80+
border: 1px solid #ccc;
81+
border-radius: 4px;
82+
font-size: 1em;
83+
background-color: #e9ecef;
84+
}
85+
.copy-button {
86+
padding: 8px 15px;
87+
background-color: #667eea;
88+
color: white;
89+
border: none;
90+
border-radius: 4px;
91+
cursor: pointer;
92+
font-size: 0.9em;
93+
transition: background-color 0.2s;
94+
}
95+
.copy-button:hover {
96+
background-color: #764ba2;
97+
}
98+
#copyStatus {
99+
margin-left: 8px;
100+
font-size: 0.9em;
101+
color: #27ae60;
102+
}
103+
</style>
104+
</head>
105+
<body>
106+
<div class="container">
107+
<h1>{{ server_name }}</h1>
108+
<p>This server provides data-related tools via the Model Context Protocol (MCP).
109+
Please note that in order for this endpoint to be reliable, it is recommended to set the minimum
110+
number of instances/processes to 1 in the content settings.</p>
111+
112+
<p>The MCP endpoint is available at:</p>
113+
<div class="mcp-endpoint-section">
114+
<input type="text" id="mcpEndpointUrl" value="{{ endpoint }}" readonly>
115+
<button class="copy-button" onclick="copyToClipboard()">Copy</button>
116+
<span id="copyStatus"></span>
117+
</div>
118+
119+
<h2>Available MCP Tools:</h2>
120+
{% if tools %}
121+
<ul>
122+
{% for tool in tools %}
123+
<li>
124+
<strong>{{ tool.name }}</strong>
125+
{{ tool.description }}
126+
{% if tool.parameters %}
127+
<div class="tool-parameters">
128+
<p><strong>Parameters:</strong></p>
129+
<ul>
130+
{% for param_name, param_details in tool.parameters.items() %}
131+
<li><code>{{ param_name }}</code> {% if param_details.required %} <strong>(required)</strong>{% endif %}: {{ param_details.type }}</li>
132+
{% endfor %}
133+
</ul>
134+
</div>
135+
{% endif %}
136+
</li>
137+
{% endfor %}
138+
</ul>
139+
{% else %}
140+
<p>No tools are currently available.</p>
141+
{% endif %}
142+
</div>
143+
144+
<script>
145+
function copyToClipboard() {
146+
const endpointUrlField = document.getElementById('mcpEndpointUrl');
147+
const copyStatus = document.getElementById('copyStatus');
148+
149+
navigator.clipboard.writeText(endpointUrlField.value).then(function() {
150+
copyStatus.textContent = 'Copied!';
151+
setTimeout(() => {
152+
copyStatus.textContent = '';
153+
}, 2000);
154+
}, function(err) {
155+
copyStatus.textContent = 'Failed to copy';
156+
console.error('Could not copy text: ', err);
157+
setTimeout(() => {
158+
copyStatus.textContent = '';
159+
}, 2000);
160+
});
161+
}
162+
</script>
163+
</body>
164+
</html>

0 commit comments

Comments
 (0)