[mcp] guides for Grafana and Notion MCP server (#62009)

* [mcp] integration guide for Grafana and Notion

* review comments
This commit is contained in:
STeve (Xin) Huang
2025-12-08 20:05:21 +00:00
committed by GitHub
parent 16afbf50ea
commit 0c6b20ce2f
16 changed files with 388 additions and 48 deletions
+1
View File
@@ -782,6 +782,7 @@
"norc",
"nosql",
"notifempty",
"notionhq",
"nowait",
"ntauth",
"nvme",
Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

@@ -28,37 +28,7 @@ Teleport-signed token.
## Step 1/3. Configure JWT authentication in Grafana
Add an `auth.jwt` section in Grafana’s main configuration file. Replace <Var
name="teleport.example.com" /> with the domain name of your Teleport cluster:
```ini
[auth.jwt]
enabled = true
# HTTP header to look into to get a JWT token.
header_name = Authorization
# JSON Web Key Set (JWKS) URL from your Teleport cluster.
jwk_set_url = https://<Var name="teleport.example.com" />/.well-known/jwks.json
# Teleport username can be found in "sub" or "username" claims.
username_claim = sub
# Map Teleport users to Grafana organization roles based on their Teleport
# roles. Adjust accordingly.
#
# In this example, if the user's Teleport role list (the "roles" claim) contains
# "editor", assign them the Grafana "Editor" role. All other users get the
# "Viewer" role.
#
# Teleport user traits are also available in the "traits" claim and can be
# used in expressions in the same way as roles.
role_attribute_path = contains(roles[*], 'editor') && 'Editor' || 'Viewer'
# auto-create users if they are not already matched.
auto_sign_up = true
```
Restart your Grafana instance after updating the config.
(!docs/pages/includes/application-access/jwt-grafana-config.mdx!)
## Step 2/3. Register a Grafana application in Teleport
@@ -8,24 +8,24 @@ tags:
- zero-trust
---
This guide demonstrates how to run a GitHub MCP server and connect it via
Teleport.
(!docs/pages/includes/mcp-access/integration-intro.mdx serviceName="GitHub" !)
## How it works
The [GitHub MCP server](https://github.com/github/github-mcp-server) uses a
personal access token of a service account to access GitHub and
[`mcp-proxy`](https://github.com/sparfenyuk/mcp-proxy) exposes it to Teleport
over a streamable-HTTP endpoint by translating the original transport. Teleport
proxies all client requests to the server, which interacts with GitHub using the
permissions granted to the service account.
[`mcp-proxy`](https://github.com/sparfenyuk/mcp-proxy) exposes it to the
Teleport Application Service over a streamable-HTTP endpoint by translating the
original transport. Teleport proxies all client requests to the server, which
interacts with GitHub using the permissions granted to the service account.
## Prerequisites
(!docs/pages/includes/edition-prereqs-tabs.mdx edition="Teleport (v18.3.0 or higher)" clients="\`tsh\` client"!)
- Access to a service account to your GitHub organization.
- A host to run the MCP server that is reachable by the Teleport Application Service.
- Running [Teleport Application Service](../getting-started.mdx).
- A running Teleport Application Service. If you have not yet done this, follow
the [Getting Started guide](../getting-started.mdx).
- A Teleport user with sufficient permissions (e.g. role `mcp-user`) to access
MCP servers.
@@ -113,7 +113,7 @@ token for the `Authorization` header:
$ tsh mcp config github-mcp --client-config claude --header "Authorization: Bearer <Var name="github_personal_access_token" />"
```
## Next Steps
## Next steps
- Review [Enroll a Streamable-HTTP MCP Server](../enrolling-mcp-servers/streamable-http.mdx).
- See the [dynamic registration](../dynamic-registration.mdx) guide.
@@ -0,0 +1,137 @@
---
title: Connect a Grafana MCP Server to Teleport
sidebar_label: Grafana
description: Set up a Grafana MCP server for access through Teleport
tags:
- how-to
- mcp
- zero-trust
---
(!docs/pages/includes/mcp-access/integration-intro.mdx serviceName="Grafana" !)
## How it works
The [Grafana MCP server](https://github.com/grafana/mcp-grafana)
forwards JWT tokens signed by Teleport to access Grafana and runs on a local
endpoint reachable by the Teleport Application Service. Teleport proxies all
client requests to the server, which interacts with Grafana using permissions
mapped by [JWT authentication](https://grafana.com/docs/grafana/latest/setup-grafana/configure-access/configure-authentication/jwt/).
## Prerequisites
(!docs/pages/includes/edition-prereqs-tabs.mdx edition="Teleport (v18.3.0 or higher)" clients="\`tsh\` client"!)
- Ability to configure your Grafana instance.
- A host to run the MCP server that is reachable by the Teleport Application Service.
- A running Teleport Application Service. If you have not yet done this, follow
the [Getting Started guide](../getting-started.mdx).
- A Teleport user with sufficient permissions (e.g. role `mcp-user`) to access
MCP servers.
## Step 1/3. Configure JWT authentication in Grafana
(!docs/pages/includes/application-access/jwt-grafana-config.mdx!)
## Step 2/3. Run the Grafana MCP server
The Grafana MCP Server can be run either as a compiled binary or via the
official Docker image:
<Tabs>
<TabItem label="mcp-grafana binary">
Run the MCP server in streamable-HTTP transport. Assign <Var name="GRAFANA_URL"
initial_value="https://your-grafana-instance-url"/> to the URL of your Grafana
instance and <Var name="MCP_HOST" initial_value="localhost" /> to the hostname
of the host machine running the MCP server:
```code
$ export GRAFANA_URL=<Var name="GRAFANA_URL" initial_value="https://your-grafana-instance-url" />
$ ./mcp-grafana --transport streamable-http --address <Var name="MCP_HOST" initial_value="localhost" />:8000
```
</TabItem>
<TabItem label="Docker">
Run the MCP server in streamable-HTTP transport. Assign <Var name="GRAFANA_URL"
initial_value="https://your-grafana-instance-url"/> to the URL of your Grafana
instance:
```code
$ docker run -d -p 8000:8000 \
-e GRAFANA_URL=<Var name="GRAFANA_URL" initial_value="https://your-grafana-instance-url" /> \
mcp/grafana --transport streamable-http
```
</TabItem>
</Tabs>
The Grafana MCP Server now exposes a streamable-HTTP endpoint at `http://<Var name="MCP_HOST"/>:8000/mcp`.
## Step 3/3. Connect via Teleport
(!docs/pages/includes/mcp-access/integration-teleport-app-rewrite.mdx service="grafana" serviceName="Grafana" port="8000" headerName="X-Grafana-API-Key" headerValue="&#123;&#123;internal.jwt&#125;&#125;" !)
The header rewrite configuration above will replace the `{{internal.jwt}}`
template variable with a Teleport-signed JWT token in each request. The Grafana
MCP server will use this token as a bearer token in "Authorization" header when
connecting to Grafana.
(!docs/pages/includes/mcp-access/integration-limit-tools.mdx!)
```yaml
kind: role
version: v8
metadata:
name: grafana-mcp-readonly
spec:
allow:
app_labels:
'service': 'grafana'
mcp:
tools:
- ^(get|query|list|search|find)_.*$
```
(!docs/pages/includes/mcp-access/integration-tsh.mdx service="grafana" serviceName="Grafana" !)
![Grafana Claude](../../../../img/mcp-access/grafana-claude.png)
## Connect to Grafana using a service account
Instead of accessing Grafana with JWT authentication, you can also use a service
account.
Navigate to Administrators > Users and Accounts > Service Accounts, and then
click **Create Service Account**:
![Grafana Service Account](../../../../img/mcp-access/grafana-create-sa.png)
Assign the **Viewer** role to keep the service account limited to read-only
access.
After the service account is created, click **Add service account
token** to generate a new token. Use this token <Var
name="SERVICE_ACCOUNT_TOKEN" initial_value="your_service_account_token"/> when
starting the Grafana MCP server:
```code
$ docker run -d -p 8000:8000 \
-e GRAFANA_URL=<Var name="GRAFANA_URL" /> \
-e GRAFANA_SERVICE_ACCOUNT_TOKEN=<Var name="SERVICE_ACCOUNT_TOKEN"/> \
mcp/grafana --transport streamable-http
```
Lastly, you don’t need to configure any header rewrites in the Teleport
application:
```yaml
app_service:
enabled: "yes"
apps:
- name: "grafana-mcp"
uri: "mcp+http://<Var name="MCP_HOST"/>:8000/mcp"
labels:
env: dev
service: grafana
```
## Next steps
- Read more on accessing Grafana through Teleport with [JWT authentication](../../application-access/jwt/grafana.mdx).
- Review [Enroll a Streamable-HTTP MCP Server](../enrolling-mcp-servers/streamable-http.mdx).
- See the [dynamic registration](../dynamic-registration.mdx) guide.
- Learn more about [mcp-grafana](https://github.com/grafana/mcp-grafana).
- Connect your [MCP clients](../../../connect-your-client/model-context-protocol/mcp-access.mdx).
@@ -0,0 +1,97 @@
---
title: Connect a Notion MCP Server to Teleport
sidebar_label: Notion
description: Set up a Notion MCP server for access through Teleport
tags:
- how-to
- mcp
- zero-trust
---
(!docs/pages/includes/mcp-access/integration-intro.mdx serviceName="Notion" !)
## How it works
The [Notion MCP server](https://github.com/makenotion/notion-mcp-server)
uses an integration token to access Notion and runs on a local endpoint
reachable by the Teleport Application Service. Teleport proxies all client
requests to the server, which interacts with Notion using the permissions
granted to the integration.
## Prerequisites
(!docs/pages/includes/edition-prereqs-tabs.mdx edition="Teleport (v18.3.0 or higher)" clients="\`tsh\` client"!)
- Access to your Notion workspace and sufficient privileges to manage integrations.
- A host to run the MCP server that is reachable by the Teleport Application Service.
- A running Teleport Application Service. If you have not yet done this, follow
the [Getting Started guide](../getting-started.mdx).
- A Teleport user with sufficient permissions (e.g. role `mcp-user`) to access
MCP servers.
## Step 1/3. Create an integration in Notion
Go to https://www.notion.so/profile/integrations and create a new **internal
integration**.
![Notion integration](../../../../img/mcp-access/notion-integration.png)
To limit the scope available to LLMs, disable all permissions except "Read
Content" in the "Capabilities" section.
Next, open "Access" tab and select the pages you want the integration to be able
to access.
![Notion access](../../../../img/mcp-access/notion-access.png)
Finally, return to the "Configuration" tab, copy the "Internal Integration
Secret" for use in the next step.
## Step 2/3. Run the Notion MCP server
Start the Notion MCP server using your Notion integration token <Var
name="ntn_your_internal_integration_secret" />:
```code
$ export NOTION_TOKEN=<Var name="ntn_your_internal_integration_secret" />
$ npx @notionhq/notion-mcp-server --transport http --port 8000 --auth-token teleport-local-connection
```
The MCP server listens on all network interfaces by default. Run it on a private
network and ensure the hostname <Var name="MCP_HOST" initial="localhost" /> is
reachable by the Teleport Application Service.
The `--auth-token` value is the shared secret Teleport uses to authenticate to
the MCP server. Since the MCP server is not publicly accessible, using a fixed
value is acceptable.
## Step 3/3. Connect via Teleport
(!docs/pages/includes/mcp-access/integration-teleport-app.mdx service="notion" serviceName="Notion" port="8000" !)
(!docs/pages/includes/mcp-access/integration-limit-tools.mdx!)
```yaml
kind: role
version: v8
metadata:
name: notion-mcp-readonly
spec:
allow:
app_labels:
'service': 'notion'
mcp:
tools:
- API-get-*
- API-retrieve-*
- API-post-database-query
- API-post-search
```
(!docs/pages/includes/mcp-access/integration-tsh.mdx service="notion" serviceName="Notion" !)
![Notion Claude](../../../../img/mcp-access/notion-claude.png)
## Next steps
- Review [Enroll a Streamable-HTTP MCP Server](../enrolling-mcp-servers/streamable-http.mdx).
- See the [dynamic registration](../dynamic-registration.mdx) guide.
- Learn more about [notion-mcp-server](https://github.com/makenotion/notion-mcp-server).
- Connect your [MCP clients](../../../connect-your-client/model-context-protocol/mcp-access.mdx).
@@ -1,5 +1,5 @@
---
title: Connect a HashiCorp Vault MCP server to Teleport
title: Connect a HashiCorp Vault MCP Server to Teleport
sidebar_label: HashiCorp Vault
description: Set up a HashiCorp Vault MCP server for access through Teleport
tags:
@@ -8,23 +8,23 @@ tags:
- zero-trust
---
This guide demonstrates how to run a HashiCorp MCP server and connect it via
Teleport.
(!docs/pages/includes/mcp-access/integration-intro.mdx serviceName="HashiCorp Vault" !)
## How it works
The [HashiCorp Vault MCP server](https://github.com/hashicorp/vault-mcp-server)
uses a service token to access HashiCorp Vault and runs on a local endpoint
reachable by Teleport. Teleport proxies all client requests to the server, which
interacts with HashiCorp Vault using the permissions granted by the policy bound
to the token.
reachable by the Teleport Application Service. Teleport proxies all client
requests to the server, which interacts with HashiCorp Vault using the
permissions granted by the policy bound to the token.
## Prerequisites
(!docs/pages/includes/edition-prereqs-tabs.mdx edition="Teleport (v18.3.0 or higher)" clients="\`tsh\` client"!)
- Access to your Vault instance and sufficient privileges to manage policies.
- A host to run the MCP server that is reachable by the Teleport Application Service.
- Running [Teleport Application Service](../getting-started.mdx).
- A running Teleport Application Service. If you have not yet done this, follow
the [Getting Started guide](../getting-started.mdx).
- A Teleport user with sufficient permissions (e.g. role `mcp-user`) to access
MCP servers.
@@ -117,7 +117,7 @@ spec:
![Vault Claude](../../../../img/mcp-access/vault-claude.png)
## Next Steps
## Next steps
- Review [Enroll a Streamable-HTTP MCP Server](../enrolling-mcp-servers/streamable-http.mdx).
- See the [dynamic registration](../dynamic-registration.mdx) guide.
@@ -17,6 +17,8 @@ import databaseSvg from "@site/src/components/Icon/teleport-svg/database.svg";
import kubernetesSvg from "@site/src/components/Icon/svg/kubernetes2.svg";
import githubSvg from "@site/src/components/Icon/svg/github.svg";
import vaultSvg from "@site/src/components/Icon/svg/hashicorp-vault.svg";
import notionSvg from "@site/src/components/Icon/svg/notion.svg";
import grafanaSvg from "@site/src/components/Icon/svg/grafana.svg";
<DocHero
title="Enroll your first MCP server"
@@ -111,11 +113,23 @@ Connect an MCP server with the Teleport Application Service, configure and assig
href: "./integration-guides/github/",
iconComponent: githubSvg,
},
{
title: "Grafana",
description: "Connect Grafana over MCP",
href: "./integration-guides/grafana/",
iconComponent: grafanaSvg,
},
{
title: "Hashicorp Vault",
description: "Connect Hashicorp Vault over MCP",
href: "./integration-guides/vault/",
iconComponent: vaultSvg,
},
{
title: "Notion",
description: "Connect Notion over MCP",
href: "./integration-guides/notion/",
iconComponent: notionSvg,
},
]}
/>
@@ -0,0 +1,31 @@
Add an `auth.jwt` section in Grafana’s main configuration file. Replace <Var
name="teleport.example.com" /> with the domain name of your Teleport cluster:
```ini
[auth.jwt]
enabled = true
# HTTP header to look into to get a JWT token.
header_name = Authorization
# JSON Web Key Set (JWKS) URL from your Teleport cluster.
jwk_set_url = https://<Var name="teleport.example.com" />/.well-known/jwks.json
# Teleport username can be found in "sub" or "username" claims.
username_claim = sub
# Map Teleport users to Grafana organization roles based on their Teleport
# roles. Adjust accordingly.
#
# In this example, if the user's Teleport role list (the "roles" claim) contains
# "editor", assign them the Grafana "Editor" role. All other users get the
# "Viewer" role.
#
# Teleport user traits are also available in the "traits" claim and can be
# used in expressions in the same way as roles.
role_attribute_path = contains(roles[*], 'editor') && 'Editor' || 'Viewer'
# auto-create users if they are not already matched.
auto_sign_up = true
```
Restart your Grafana instance after updating the config.
@@ -0,0 +1,7 @@
Teleport can provide secure access to MCP servers via Teleport Application
Service.
In this guide, you will:
1. Configure your {{ serviceName }} service for access by the MCP server.
1. Run the {{ serviceName }} MCP Server.
1. Enroll the MCP server into your Teleport cluster and connect to it.
@@ -0,0 +1,83 @@
You can register an MCP application in Teleport by defining it in your Teleport
Application Service configuration, or by using dynamic registration with `tctl`
or Terraform:
<Tabs>
<TabItem label="Static configuration">
Replace <Var name="MCP_HOST"/> with the host running the {{serviceName}} MCP server:
```yaml
app_service:
enabled: "yes"
apps:
- name: "{{service}}-mcp"
uri: "mcp+http://<Var name="MCP_HOST"/>:{{port}}/mcp"
labels:
env: dev
service: {{service}}
rewrite:
headers:
- "{{headerName}}: {{headerValue}}"
```
Restart the Application Service.
</TabItem>
<TabItem label="tctl">
Create an `app` resource definition file named `app-{{service}}-mcp.yaml`. Replace
<Var name="MCP_HOST" /> with the host running the {{serviceName}} MCP server:
```yaml
# app-{{service}}-mcp.yaml
kind: app
version: v3
metadata:
name: {{service}}-mcp
labels:
env: dev
service: {{service}}
rewrite:
headers:
- name: "{{headerName}}"
value: "{{headerValue}}"
spec:
uri: "mcp+http://<Var name="MCP_HOST" />:{{port}}/mcp"
```
Create the `app` resource with:
```code
$ tctl create -f app-{{service}}-app.yaml
```
</TabItem>
<TabItem label="Terraform">
Create a `teleport_app` resource in terraform. Replace <Var name="MCP_HOST" />
with the host running the {{serviceName}} MCP server:
```hcl
resource "teleport_app" "grafana" {
version = "v3"
metadata = {
name = "grafana"
labels = {
"teleport.dev/origin" = "dynamic"
"env" = "dev"
"service" = "{{service}}"
}
}
spec = {
uri = "mcp+http://<Var name="MCP_HOST" />:{{port}}/mcp"
rewrite = {
headers = [{
name = "{{headerName}}"
value = "{{headerValue}}"
}]
}
}
}
```
Apply the configuration:
```code
$ terraform apply
```
</TabItem>
</Tabs>
@@ -52,7 +52,7 @@ resource "teleport_app" "grafana" {
labels = {
"teleport.dev/origin" = "dynamic"
"env" = "dev"
"service" = ""{{service}}""
"service" = "{{service}}"
}
}