Skip to main content
Glama
mgcrea

mcp-ovh-api

by mgcrea

@mgcrea/mcp-ovh-api

npm version GHCR

一个面向 OVHcloud APIModel Context Protocol 服务器,专注于对象存储:存储桶、对象、项目用户、S3 凭证以及将它们关联在一起的存储策略。

该服务器默认只读。当写入未开启时,变更工具不仅仅是被拒绝——它们根本不会被注册,因此代理完全无法调用它们。

功能特性

  • 基于 OVHcloud 的 /1.0 API 精选工具,其描述阐明了其中的陷阱(请参阅值得了解的陷阱)。

  • 默认只读。 OVH_ALLOW_WRITES=1 会注册写入工具;而破坏性工具在每次调用时还额外要求显式的 confirm: true

  • 支持全部三种 OVH 认证方式,会根据存在的环境变量自动选择:OAuth2 服务账户(推荐)、应用密钥 + 消费者密钥(SHA1 签名,带自动时钟漂移校正)或静态访问令牌

  • 策略预设——包括 OVH 自身角色快捷方式不提供的 write-only

  • 列表结果会被汇总,并且 OVH 已弃用的按存储桶 objects[] 数组(其中嵌入了存储桶中的每个对象)在两端都会被抑制。

  • X-Ovh-QueryID 会在每个错误中显示,因为这是 OVH 支持人员首先会询问的信息。

  • 提供 ovh_request 逃生舱口以访问 API 的其余部分(除非启用写入,否则仅限 GET)。

  • 原生 fetch,除 MCP SDK 和 Zod 外无运行时依赖。

Related MCP server: saveformedearai

安装

pnpm install
pnpm build

配置

选择一种认证方式。

(A) OAuth2 服务账户 — 推荐

  1. https://www.ovh.com/manager/#/iam/service-account 创建 IAM 服务账户。

  2. 附加一个 IAM 策略,授予其对公共云项目的访问权限(对于对象存储:项目资源上的 publicCloudProject:apiovh:*)。

  3. 将客户端 ID 和密钥复制到 .env 中。

令牌有效期为一小时,会提前缓存并在过期前刷新。

(B) 应用密钥 + 消费者密钥

https://eu.api.ovh.com/createToken/ 一次性创建三元组。你在此列出的访问规则将永久固定——消费者密钥之后无法扩大范围,因此请预先授予所需权限:

GET    /cloud/project/*
POST   /cloud/project/*
PUT    /cloud/project/*
DELETE /cloud/project/*
GET    /me

请求使用 secret+consumerKey+METHOD+URL+BODY+TIMESTAMP 进行 SHA1 签名。如果时钟与 OVH 相差超过约 30 秒,则每次调用都会以误导性的 Invalid signature 失败,因此服务器会在启动时探测一次 /auth/time 并校正差值。

(C) 静态访问令牌

设置 OVH_ACCESS_TOKEN,它将作为 Authorization: Bearer 发送。

cp .env.example .env

变量

必需

描述

OVH_ENDPOINT

ovh-eu(默认)、ovh-caovh-uskimsufi-*soyoustart-*

OVH_CLIENT_ID / OVH_CLIENT_SECRET

(A)

IAM 服务账户。它们的存在会选择 OAuth2。

OVH_APPLICATION_KEY / _SECRET

(B)

应用密钥对。

OVH_CONSUMER_KEY

(B)

随其一起签发的消费者密钥。

OVH_ACCESS_TOKEN

(C)

预铸造的 Bearer 令牌。

OVH_AUTH_METHOD

强制指定 oauth2signatureaccessToken。否则自动推断。

OVH_CLOUD_PROJECT

默认项目 — 32 位十六进制 serviceName,而非显示名称。

OVH_REGION

默认存储区域,大写(GRASBGDEUK)。

OVH_ALLOW_WRITES

设置为 1 以注册写入工具。默认关闭。

OVH_API_URL

完全覆盖 API 基础 URL。

OVH_MAX_RETRIES

401 / 429 / 5xx 的重试预算。默认为 3

OVH_REFRESH_SKEW_SECONDS

在过期前这么久刷新 OAuth2 令牌。默认为 60

OVH_DEBUG

设置为 1 以将调试输出记录到 stderr。

运行

pnpm start   # speaks JSON-RPC over stdio

接入 Claude Code

添加到 .mcp.json(项目)或 ~/.claude.json(全局):

{
  "mcpServers": {
    "ovh": {
      "command": "node",
      "args": ["/absolute/path/to/mcp-ovh-api/dist/cli.js"],
      "env": {
        "OVH_CLIENT_ID": "...",
        "OVH_CLIENT_SECRET": "...",
        "OVH_CLOUD_PROJECT": "abcdef0123456789abcdef0123456789",
        "OVH_REGION": "UK"
      }
    }
  }
}

检查工具

npx @modelcontextprotocol/inspector node dist/cli.js

值得了解的陷阱

所有这些都已融入工具描述中,但它们解释了此服务器的形态:

  1. OVH 没有存储桶策略——只有用户策略。 每个项目用户一份原始 JSON 文档,而该文档就是整个访问控制面。设置策略会替换该用户之前在所有存储桶上可以执行的所有操作。

  2. 策略无法限制存储桶的所有者。 OVH 会回退到 ACL,而所有者拥有 FULL_CONTROL"如果用户是存储桶所有者,即使策略文件中没有显式允许,该用户也将被授权。" 因此,受限密钥必须属于一个新的项目用户,而不是创建该存储桶的用户。ovh_provision_s3_user 会检查存储桶的 ownerId,并在你将其指向所有者时拒绝。

  3. 同样的回退也适用于每个对象。 上传对象的任何人都拥有它,并通过对象 ACL 对其拥有 FULL_CONTROL。因此,仅仅省略 s3:GetObject不能阻止仅上传的密钥读回其写入的所有内容——这已针对实时 API 验证过,一个裸允许列表策略可以愉快地为其密钥提供自己的上传内容,同时正确拒绝其他人上传的每个对象。显式的 Deny 必需的,而且它确实胜过 ACL。这就是为什么 write-only 预设附带一个 Deny 语句,而不是裸允许列表。

还有两个较小的问题。单独的 s3:PutObject 仍然允许在允许的前缀内盲目覆盖现有密钥——"只写"密钥不是仅追加密钥,这是为存储桶启用版本控制的一个很好的理由。此外,策略更改需要长达约 30 秒才能生效:在 ovh_set_storage_policy 之后五秒进行的探测运行仍然显示旧行为,这看起来就像策略静默失败了一样。

工具

每个项目范围的工具都接受可选的 project,每个存储工具都接受可选的 region,以覆盖每次调用的 OVH_CLOUD_PROJECT / OVH_REGION。标记为 W 的工具仅在 OVH_ALLOW_WRITES=1 时存在;标记为 ⚠️ 的工具具有破坏性,并且额外要求 confirm: true

ovh_whoami 开始。 它报告哪种认证方法处于活动状态、你是哪个账户以及相对于 OVH 的时钟偏差——这几乎总是签名方法上出现 401 的原因。

区域

工具

元数据

ovh_whoami, ovh_list_projects, ovh_get_project, ovh_list_regions, ovh_get_region

存储桶

ovh_list_buckets, ovh_get_bucket, ovh_get_bucket_lifecycle · W ovh_create_bucket, ovh_update_bucket, ovh_set_bucket_lifecycle, ⚠️ ovh_delete_bucket_lifecycle, ⚠️ ovh_delete_bucket

对象

ovh_list_objects, ovh_get_object, ovh_list_object_versions, ovh_presign_object · W ovh_copy_object, ⚠️ ovh_delete_object, ⚠️ ovh_delete_object_version, ⚠️ ovh_bulk_delete_objects

用户与密钥

ovh_list_project_users, ovh_get_project_user, ovh_list_s3_credentials · W ovh_create_project_user, ovh_create_s3_credentials, ovh_reveal_s3_secret, ⚠️ ovh_delete_s3_credentials, ⚠️ ovh_delete_project_user

策略

ovh_get_storage_policy, ovh_preview_policy · W ⚠️ ovh_set_storage_policy, ⚠️ ovh_grant_bucket_access, ⚠️ ovh_provision_s3_user

逃生舱口

ovh_request — 任何 /1.0 路径,除非启用写入,否则仅限 GET

ovh_presign_object 是字节移动的唯一方式:服务器从不代理对象内容,而是生成一个限时预签名 S3 URL。关闭写入时,它仅对 GET 签名。

策略预设

ovh_preview_policyovh_set_storage_policyovh_provision_s3_user 共享三个预设,所有预设都可以限定到密钥前缀:

预设

授予的权限

write-only

允许前缀上的 s3:PutObjects3:AbortMultipartUploads3:ListMultipartUploadParts外加存储桶范围内对 s3:GetObject / s3:GetObjectAcl 的显式 Deny

read-only

存储桶上的 s3:ListBucket + s3:GetBucketLocation,对象上的 s3:GetObject

read-write

两者兼有,外加 s3:DeleteObject

OVH 的内置角色(admindenyreadOnlyreadWrite,通过 ovh_grant_bucket_access)没有只写等效项——这就是原始策略路径存在的原因。多部分对是故意包含的:每个 S3 SDK 都会在约 8-16MB 以上自动切换到多部分,如果没有中止/列出,失败的上传会使密钥持有者无法清理孤立的部分,并持续为此付费。

OVH 会根据固定的枚举验证策略操作,如果某个操作未知,则会以 400 拒绝整个文档——s3:GetObjectVersions3:DeleteObjectVersion 存在于 AWS 中,但不存在于此。预设仅使用接受的操作,并且测试固定了这一点。

分发只写上传密钥

动机案例:应用在发布的二进制文件中嵌入了 S3 密钥,因此该密钥必须能够上传而不能做其他任何事情,而读/写密钥则保留在开发人员手中。

ovh_get_bucket           bucket=dev-rgis-ar          → note ownerId
ovh_preview_policy       bucket=dev-rgis-ar preset=write-only prefix=uploads/
ovh_provision_s3_user    bucket=dev-rgis-ar preset=write-only prefix=uploads/ \
                         description=ar-app-uploader confirm=true

这会创建一个新的项目用户(绝不是存储桶所有者),应用策略,然后才铸造凭证——在策略之前存在的密钥是一个短暂拥有默认允许的任何权限的密钥。密钥只返回一次。

在移交之前对照真实的 S3 API 进行验证——正确读取的策略仍可能被所有权遮蔽,并且在设置后等待约 30 秒,否则你探测的将是以前的策略:

export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=...
# An array, not a string: zsh does not word-split an unquoted $var, so the
# `S3='aws ...'` form you would write in bash silently becomes "command not found".
S3=(aws --endpoint-url https://s3.uk.io.cloud.ovh.net --region uk s3api)
"${S3[@]}" put-object      --bucket dev-rgis-ar --key uploads/probe.txt --body /dev/null   # 200
"${S3[@]}" get-object      --bucket dev-rgis-ar --key uploads/probe.txt /dev/null          # 403
"${S3[@]}" list-objects-v2 --bucket dev-rgis-ar                                            # 403
"${S3[@]}" delete-object   --bucket dev-rgis-ar --key uploads/probe.txt                    # 403
"${S3[@]}" put-object      --bucket dev-rgis-ar --key elsewhere/probe.txt --body /dev/null # 403

get-object 行才是关键:这是捕获陷阱 3 的检查,并且仅仅因为预设的 Deny 而通过。

开发

pnpm dev            # tsdown --watch
pnpm test           # vitest
pnpm typecheck
pnpm lint
pnpm format

许可证

MIT

Available Tools

1 tool
ovh_auth_statusOVHcloud: Auth StatusA
Read-only

Report whether this server has working OVHcloud credentials, which auth method and endpoint it uses, the default project and region, whether writes are enabled, and — when something is missing — exactly what to set. Call this first when a tool you expected is not listed: an absent tool here means missing configuration, not a bug.

ParametersJSON Schema
NameRequiredDescriptionDefault

No parameters

TDQS

A4.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

The readOnlyHint annotation already marks this as safe, and the description adds useful behavioral context by stating it reports credential validity, auth method, endpoint, project/region, and write status. It also says missing credentials explain absent tools, which clarifies what the status check means. It doesn't explicitly describe network/read behavior, but the annotation plus 'report' wording make the safety profile clear.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences carry a full purpose statement, a detailed list of outputs, and a usage rule. The key diagnostic trigger ('Call this first when a tool you expected is not listed') is placed second and is memorable. No word is wasted.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with no parameters, no siblings, and no output schema, the description is self-sufficient: it tells the agent what information the tool produces and when to invoke it. The only omitted detail, the exact configuration values to set, is precisely what the tool's output is described as providing.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

There are zero parameters, so there is nothing to document beyond the empty schema. The description still clarifies the kind of status data returned, which is consistent with a no-input diagnostic tool. Baseline 4 is appropriate for a 0-parameter definition.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description opens with a specific verb and resource: 'Report whether this server has working OVHcloud credentials,' then enumerates exactly what is reported (auth method, endpoint, default project/region, write enablement). This is unambiguous and fully distinguishes the tool from any conceivable alternative, even though no siblings are listed.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

It gives an explicit call heuristic: 'Call this first when a tool you expected is not listed,' and even frames the diagnostic interpretation ('an absent tool here means missing configuration, not a bug'). This tells an agent not only when to run it but how to interpret the result.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4.2/5.0
Disambiguation5/5

With only one tool, there is no possibility of confusion between tools. The single tool's purpose is clearly defined and distinct.

Naming Consistency5/5

The lone tool name follows a clean snake_case verb_noun pattern. With only one tool, there are no inconsistencies to evaluate.

Tool Count1/5

A single status-check tool is drastically insufficient for a server named 'mcp-ovh-api' covering the OVH cloud API. The count represents an extreme mismatch between the server's implied scope and its actual surface.

Completeness1/5

The server exposes no operations beyond an authentication status check. Any actual OVH API functionality is absent, making the tool surface severely incomplete for the stated domain.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    MCP server for uploading, listing, and retrieving files on S3-compatible storage (AWS S3, DigitalOcean Spaces) with public/private access and temporary URLs.
    15
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    MCP server for Oracle Cloud Infrastructure (OCI) that provides tools to manage Compute, Object Storage, Block Storage, Networking, Autonomous Database, and IAM via the official OCI SDK.
    23
    67
    MIT

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/mgcrea/mcp-ovh'

If you have feedback or need assistance with the MCP directory API, please join our Discord server