编程 Anthropic 22亿收购Stainless:当SDK自动生成成为AI战争的战略高地

2026-05-19 15:49:10 +0800 CST views 63

Anthropic 22亿收购Stainless:当SDK自动生成成为AI战争的战略高地

一、事件速览:AI工具链的"核武器级"收购

2026年5月18日(太平洋时间),Anthropic宣布收购AI基础设施初创公司Stainless。据多方报道,收购金额超过2.8亿欧元(约合22.18亿元人民币),部分信源甚至称超过3亿美元。

这不是一次普通的"买买买"。Stainless不是某款应用或某个模型——它是AI行业底层基础设施中的基础设施。OpenAI、Google、Anthropic自己的官方SDK,全都依赖它来生成和维护。

收购完成后,Stainless将关闭全部面向外部客户的托管服务。这意味着OpenAI、Google等竞争对手将失去一个关键的SDK自动生成工具。这不仅仅是商业收购,更是一次战略封锁。

二、Stainless到底是什么?为什么值22亿?

2.1 从API规范到多语言SDK:自动化的魔法

Stainless成立于2022年,由Alex Rattray创立,总部位于美国旧金山。它的核心产品极其简洁却极其强大:

将OpenAPI规范自动转化为多语言SDK。

听起来简单?让我用一个具体例子说明这有多重要。

假设你是一家AI公司,维护着一套包含200+个端点的REST API。你需要为以下语言提供官方SDK:

  • Python
  • TypeScript/JavaScript
  • Go
  • Java
  • Kotlin
  • Ruby
  • .NET/C#

每当你API变更(新增参数、修改返回结构、废弃旧端点),你需要手动更新7个语言版本的SDK。每个SDK都有类型定义、请求构造、响应解析、错误处理、分页逻辑……这是一个人工噩梦。

Stainless的做法是:

OpenAPI Spec (YAML/JSON)
        ↓
   Stainless Engine
        ↓
┌───────┬───────┬───────┬───────┬───────┐
│ Python│   TS  │  Go   │ Java  │ Kotlin│
└───────┴───────┴───────┴───────┴───────┘

一次定义,七种语言同步生成,API变更时自动更新。

2.2 不只是代码生成:开发者体验的完整链路

Stainless的价值远超简单的代码生成。它的产品矩阵包括:

1. SDK自动生成与维护

  • 生成的不是模板代码,而是生产级SDK
  • 包含完整的类型标注、错误处理、重试逻辑、分页支持
  • 支持流式响应(streaming)、异步调用等现代API特性
  • 遵循各语言生态的惯用模式(idiomatic)

2. 实时同步API文档

  • API变更后文档即时更新
  • 交互式文档,可直接在线测试
  • 多语言代码示例自动生成

3. MCP服务器解决方案

  • 这是2026年最关键的新方向
  • 将API自动包装为MCP(Model Context Protocol)服务器
  • 让AI Agent能够直接调用API工具
  • Anthropic收购Stainless后,Claude生态的MCP工具链将获得巨大优势

2.3 谁在用Stainless?

在收购之前,Stainless的客户名单读起来像是AI行业的"名人堂":

  • Anthropic — Claude API的所有官方SDK都由Stainless生成和维护
  • OpenAI — GPT系列API的官方SDK同样依赖Stainless
  • Google — Gemini等AI服务的SDK生成
  • Anthropic官网列出的客户还包括众多API优先的科技公司

这就是问题的核心:一个工具同时服务于AI行业最大的几家竞争对手。而现在,这个工具被其中一家独占了。

三、深度解析:Stainless的技术架构

3.1 OpenAPI规范:一切的基础

要理解Stainless的价值,首先需要理解OpenAPI规范(原名Swagger)。

OpenAPI是一个描述REST API的标准格式,通常使用YAML编写。一个典型的OpenAPI规范定义了:

openapi: 3.1.0
info:
  title: Claude API
  version: '2026-05-19'
paths:
  /v1/messages:
    post:
      operationId: createMessage
      summary: Create a message
      requestBody:
        required: true
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/CreateMessageRequest'
      responses:
        '200':
          description: Successful response
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/MessageResponse'
components:
  schemas:
    CreateMessageRequest:
      type: object
      required:
        - model
        - messages
        - max_tokens
      properties:
        model:
          type: string
          description: The model to use
        messages:
          type: array
          items:
            $ref: '#/components/schemas/Message'
        max_tokens:
          type: integer
          description: Maximum tokens to generate
        stream:
          type: boolean
          default: false
          description: Whether to stream responses

这段规范定义了一个createMessage接口。Stainless能将这段YAML自动转换为:

Python SDK:

import anthropic

client = anthropic.Anthropic(api_key="sk-ant-...")

message = client.messages.create(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[
        {"role": "user", "content": "Hello, Claude!"}
    ],
    stream=False
)

print(message.content[0].text)

TypeScript SDK:

import Anthropic from '@anthropic-ai/sdk';

const client = new Anthropic({ apiKey: 'sk-ant-...' });

const message = await client.messages.create({
    model: 'claude-sonnet-4-20250514',
    max_tokens: 1024,
    messages: [{ role: 'user', content: 'Hello, Claude!' }],
    stream: false,
});

console.log(message.content[0].text);

Go SDK:

package main

import (
    "context"
    "fmt"
    anthropic "github.com/anthropics/anthropic-sdk-go"
)

func main() {
    client := anthropic.NewClient()
    
    msg, err := client.Messages.New(context.Background(), anthropic.MessageNewParams{
        Model:     anthropic.F(anthropic.ModelClaude3_5Sonnet20241022),
        MaxTokens: anthropic.F(1024),
        Messages: anthropic.F([]anthropic.MessageParam{
            {Role: anthropic.F(anthropic.MessageParamRoleUser), Content: anthropic.F(anthropic.NewUnionOfMessageParamContent(anthropic.NewMessageParamContentBlock("Hello, Claude!")))},
        }),
    })
    if err != nil {
        panic(err)
    }
    fmt.Println(msg.Content[0].Text)
}

注意这些SDK代码中风格各异但都非常符合各自语言的惯用模式——这不是简单的字符串模板替换能做到的。

3.2 Stainless的代码生成架构

Stainless的生成引擎不是简单的模板系统。根据其公开的技术分享和SDK输出质量分析,其架构大致如下:

┌─────────────────────────────────────────────┐
│              OpenAPI Spec Parser             │
│  - 解析YAML/JSON规范                         │
│  - 验证规范完整性与一致性                      │
│  - 解析引用关系($ref展开)                   │
│  - 提取操作、模型、枚举等结构                  │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│           Intermediate Representation         │
│  - 语言无关的API语义模型                      │
│  - 操作列表、参数映射、类型层次               │
│  - 错误码体系、分页模式、流式处理标记           │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│         Language-Specific Generators          │
│                                              │
│  ┌────────┐ ┌────────┐ ┌──────┐ ┌────────┐ │
│  │Python  │ │   TS   │ │  Go  │ │ Java   │ │
│  │Generator│ │Generator│ │Generator│ │Generator│ │
│  └────────┘ └────────┘ └──────┘ └────────┘ │
│                                              │
│  每个Generator包含:                          │
│  - 类型映射策略(如OpenAPI string→TS string) │
│  - 代码风格模板(命名规范、文件结构)          │
│  - 异步模式适配(async/await vs callback)     │
│  - 错误处理模式(exception vs Result type)    │
│  - 测试代码生成                               │
└──────────────────┬──────────────────────────┘
                   ↓
┌─────────────────────────────────────────────┐
│           Post-Processing & Validation        │
│  - 代码格式化(black, prettier, gofmt等)     │
│  - 类型检查(mypy, tsc, go vet等)           │
│  - Lint检查                                  │
│  - 自动生成单元测试                           │
└─────────────────────────────────────────────┘

3.3 代码质量:为什么生成的SDK如此"像人写的"

评判一个SDK生成工具的关键标准是:生成的代码是否像人类手写的一样好?

以Anthropic的Python SDK为例,观察Stainless生成的几个细节:

1. 智能类型标注

from typing import Union, Literal, overload
from anthropic.types import TextBlock, ToolUseBlock

@overload
def create(
    self,
    *,
    model: str,
    messages: list[MessageParam],
    max_tokens: int,
    stream: Literal[False] = False,
    **kwargs,
) -> Message: ...

@overload
def create(
    self,
    *,
    model: str,
    messages: list[MessageParam],
    max_tokens: int,
    stream: Literal[True],
    **kwargs,
) -> Stream[MessageStreamEvent]: ...

注意@overload装饰器的使用——当stream=False时返回Message对象,当stream=True时返回Stream对象。这是Python类型系统的正确用法,而不仅仅是运行时的类型提示。

2. 惯用的异步模式

# 同步版本
client = Anthropic()
message = client.messages.create(...)

# 异步版本
client = AsyncAnthropic()
message = await client.messages.create(...)

Python的异步生态有自己的惯用模式。Stainless不是简单地把所有方法前面加async,而是正确地使用了httpx的异步客户端,保持了与同步版本一致的API设计。

3. 流式响应的优雅处理

with client.messages.stream(
    model="claude-sonnet-4-20250514",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Hello!"}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

使用上下文管理器和生成器模式处理流式响应,这是Python开发者期望的惯用写法。

4. Go的类型安全

// Go生成的SDK使用了强类型的参数对象
params := anthropic.MessageNewParams{
    Model:     anthropic.ModelClaude3Opus20240229,
    MaxTokens: anthropic.Int(1024),
    Messages: []anthropic.MessageParam{
        anthropic.NewUserMessage(
            anthropic.NewTextBlock("Hello, Claude!"),
        ),
    },
}

Go的SDK使用了函数选项模式(functional options)和强类型参数对象,避免了map[string]interface{}的松散类型。这是高质量Go库的标准做法。

这些细节说明Stainless的生成引擎对每种目标语言的惯用模式有深入理解,远不是简单的模板替换。

四、MCP连接器:Stainless的2026新王牌

4.1 MCP是什么?为什么它至关重要

MCP(Model Context Protocol)是Anthropic于2024年底推出的开放协议,用于让AI模型与外部工具和数据源交互。你可以把它理解为AI时代的USB接口标准

┌──────────┐     MCP      ┌──────────┐
│  Claude   │ ◄─────────► │  Tool A  │
│  GPT-4o   │             │  DB      │
│  Gemini   │             │  API X   │
└──────────┘             │  FS      │
                         └──────────┘

MCP的核心思想是:任何AI模型都可以通过统一协议访问任何外部工具。开发者只需要编写一个MCP Server,所有支持MCP的AI客户端都能使用。

4.2 Stainless的MCP服务器生成

Stainless在2025-2026年推出的MCP服务器生成功能,是其战略价值的关键转折点:

传统的API集成方式:

API Spec → SDK → 开发者手动封装 → MCP Server

Stainless的方式:

API Spec → 自动生成MCP Server

一步到位。任何有OpenAPI规范的API,Stainless都能自动将其转换为MCP服务器,让Claude(或其他AI模型)可以直接调用。

想象一下这个场景:

# 传统方式:你需要手动写MCP Server
class WeatherMCPServer:
    @mcp.tool()
    def get_weather(self, city: str) -> dict:
        # 调用天气API
        response = requests.get(f"https://api.weather.com/v1/{city}")
        return response.json()

# Stainless方式:直接从API规范生成
# stainless.json 配置:
# {
#   "mcp": {
#     "enabled": true,
#     "serverName": "weather-api"
#   }
# }
# 运行 stainless generate → 自动产出MCP Server代码

这就是Anthropic收购Stainless的真正战略意图:控制AI Agent的"工具接口层"

当每个AI公司都在争夺Agent生态时,谁能让开发者最快、最方便地将API接入AI Agent,谁就掌握了生态的入口。

4.3 数据流:Stainless MCP生成的完整架构

┌─────────────────────────────────────────┐
│           OpenAPI Specification          │
│  (任何API的标准描述文档)                    │
└──────────────────┬──────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│         Stainless MCP Generator          │
│                                          │
│  1. 解析API端点为MCP Tools               │
│  2. 生成JSON Schema用于参数验证            │
│  3. 生成请求/响应的类型映射                │
│  4. 处理认证(API Key, OAuth等)           │
│  5. 生成错误处理和重试逻辑                 │
└──────────────────┬──────────────────────┘
                   ↓
┌─────────────────────────────────────────┐
│           MCP Server (生产就绪)           │
│                                          │
│  ✅ 自动注册所有API端点为MCP Tools        │
│  ✅ 完整的类型安全和参数验证               │
│  ✅ 内置认证管理                          │
│  ✅ 支持流式响应                          │
│  ✅ 自带速率限制处理                      │
│  ✅ 内置日志和监控                        │
└─────────────────────────────────────────┘

五、战略分析:Anthropic的棋局

5.1 为什么是Anthropic?

表面上看,Anthropic不是最大的AI公司。OpenAI有更多用户,Google有更多资源。但Anthropic在开发者工具层面的布局一直非常激进:

  • Claude Code — AI编程助手,直接在终端使用
  • MCP协议 — 定义AI工具调用标准
  • Anthropic SDK — 多语言API客户端
  • 收购Stainless — 控制SDK和MCP生成基础设施

这些布局形成了一个闭环

Claude Code → 使用MCP协议 → 调用各种API工具
                                    ↑
                            Stainless自动生成MCP Server
                                    ↑
                                Anthropic独占

5.2 对竞争对手的影响

OpenAI:最直接的受害者

OpenAI的Python和TypeScript官方SDK长期依赖Stainless生成。收购后:

  • OpenAI需要自行搭建SDK生成基础设施,或寻找替代方案
  • 在SDK质量和更新速度上可能出现短暂滞后
  • MCP工具链的集成优势被Anthropic独占

Google:同样受影响

Google的Gemini API SDK也在使用Stainless。虽然Google有庞大的工程团队可以自行开发替代品,但迁移需要时间和资源。

开源社区:真正的长期影响

Stainless关闭外部托管服务后,开源项目将失去一个关键的SDK生成工具。虽然 Stainless 的生成引擎是闭源的,但其理念和方法论已经影响了整个行业。预计将出现以下替代方案:

  1. OpenAPI Generator — 最成熟的开源替代方案,已有8年历史
  2. Kiota — 微软推出的OpenAPI SDK生成器
  3. Speakeasy — 另一个SDK生成平台,但规模较小
  4. 各AI公司自建 — OpenAI和Google可能各自建设

5.3 Anthropic的生态护城河

收购Stainless后,Anthropic构建了一个三层护城河:

第一层:Claude模型本身
  ↓  模型能力决定AI应用的上限
第二层:MCP协议 + Claude Code
  ↓  工具调用标准 + 最佳开发者体验
第三层:Stainless(SDK + MCP Server生成)
     独占的API→AI工具转化引擎

第三层是最容易被忽视的,但可能也是最长远的。当每个API提供商都能一键将其API变成Claude可用的工具时,Claude的工具生态将自然而然地超越竞争对手。

六、开发者视角:这对你意味着什么?

6.1 如果你正在使用Stainless

如果你或你的团队是Stainless的外部客户(非Anthropic),你需要:

  1. 评估影响:你已生成的代码归你所有,但不再获得官方更新

  2. 制定迁移计划

    • 短期:fork已生成的SDK,自行维护
    • 中期:评估OpenAPI Generator等替代方案
    • 长期:可能需要自建代码生成流水线
  3. 应急方案

# 如果你的API spec在GitHub上
# 可以设置CI流水线,使用OpenAPI Generator替代
docker run --rm -v ${PWD}:/local openapitools/openapi-generator-cli generate \
  -i /local/openapi.yaml \
  -g python \
  -o /local/generated/python-sdk \
  --additional-properties=packageName=my_api_sdk

6.2 如果你在构建MCP服务器

Anthropic独占Stainless的MCP生成能力后,你的选择:

方案A:使用Anthropic生态

  • 如果你的目标用户主要是Claude用户,这是最佳路径
  • Anthropic可能会开放部分Stainless能力给生态伙伴

方案B:使用开源替代

# 使用 mcp 包手动构建MCP Server
from mcp.server.fastmcp import FastMCP
import httpx

mcp = FastMCP("my-api-server")

@mcp.tool()
async def search(query: str, limit: int = 10) -> list[dict]:
    """Search the API"""
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            "https://api.example.com/search",
            params={"q": query, "limit": limit}
        )
        return resp.json()

方案C:等待市场反应

  • 开源社区很可能会推出Stainless的替代品
  • MCP协议本身是开放的,Anthropic控制的是生成工具,不是协议标准

6.3 如果你在选择AI平台的SDK

现在SDK质量已经成为AI平台竞争的一个维度:

维度Anthropic (收购后)OpenAIGoogle
SDK生成速度⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
多语言覆盖⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐
MCP集成⭐⭐⭐⭐⭐⭐⭐⭐⭐
文档自动同步⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐⭐

短期内Anthropic的SDK体验将领先竞争对手。但这也会倒逼OpenAI和Google加速自建能力。

七、行业展望:API基础设施的"军备竞赛"

7.1 API-First时代的工具链竞争

现代软件开发正在经历一个根本性转变:API-first设计从最佳实践变成了默认模式

在这个背景下,SDK生成工具成为了关键基础设施:

2020年以前:每个API手动写SDK
  → 耗时数周,维护成本高

2020-2024年:OpenAPI Generator主导
  → 自动化程度提高,但生成质量参差不齐

2024-2025年:Stainless崛起
  → 生成质量接近手写,被AI公司广泛采用

2026年5月:Anthropic收购Stainless
  → SDK生成成为战略资产

7.2 预测:接下来会发生什么

短期(1-3个月):

  • OpenAI和Google加速自建SDK生成流水线
  • 开源社区出现多个"Stainless替代"项目
  • MCP生态可能出现分叉风险

中期(3-12个月):

  • 微软可能通过Kiota+Copilot的组合推出竞争方案
  • 大型科技公司开始将API基础设施视为战略投资
  • SDK生成工具市场可能出现新的独角兽

长期(1-3年):

  • AI Agent成为主要的API消费者
  • MCP或类似协议成为API集成的默认标准
  • "API→AI工具"的自动转化成为每家API公司的标配

7.3 更深层的思考:基础设施的垄断与开放

这次收购引发了一个关键问题:关键基础设施应该由谁来控制?

Stainless在收购前是一个中立的基础设施提供商,服务于所有AI公司。收购后,它变成了Anthropic的独占资产

这与之前的几次"基础设施收购"有相似之处:

  • GitHub被微软收购(开发者代码托管)
  • npm被GitHub收购(JavaScript包管理)
  • Docker Desktop商业化的争议(容器基础设施)

每一次,当一个关键的中立基础设施被单一公司控制时,都会引发社区对开放性和公平竞争的担忧。

MCP协议本身是开放的(Anthropic已将其开源),但生成MCP服务器的最佳工具现在被Anthropic独占。这是"协议开放、工具封闭"的典型模式。

八、技术实战:如何用开源工具替代Stainless

既然Stainless不再对外服务,开发者需要了解如何使用开源工具构建类似的流水线。以下是完整的替代方案。

8.1 OpenAPI Generator:最成熟的开源方案

OpenAPI Generator支持超过70种语言和格式的代码生成,是目前最成熟的开源替代方案。

安装:

# macOS
brew install openapi-generator-cli

# 或使用Docker
docker pull openapitools/openapi-generator-cli

# 或使用npm
npm install @openapitools/openapi-generator-cli -g

生成Python SDK:

openapi-generator-cli generate \
  -i openapi.yaml \
  -g python \
  -o ./sdk/python \
  --additional-properties=packageName=my_api_sdk,generateSourceCodeOnly=true

生成TypeScript SDK:

openapi-generator-cli generate \
  -i openapi.yaml \
  -g typescript-axios \
  -o ./sdk/typescript \
  --additional-properties=supportsES6=true,npmName=@myorg/my-api-sdk

配置CI/CD自动化:

# .github/workflows/sdk-generation.yml
name: Generate SDKs

on:
  push:
    paths:
      - 'openapi.yaml'
      - 'openapi.json'

jobs:
  generate:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        lang: [python, typescript-axios, go, java]
    steps:
      - uses: actions/checkout@v4
      
      - name: Generate ${{ matrix.lang }} SDK
        uses: openapitools/openapi-generator-action@v1
        with:
          generator: ${{ matrix.lang }}
          input: openapi.yaml
          output: ./sdk/${{ matrix.lang }}
      
      - name: Run tests
        working-directory: ./sdk/${{ matrix.lang }}
        run: |
          # 各语言特定的测试命令
          make test
      
      - name: Create PR
        uses: peter-evans/create-pull-request@v6
        with:
          title: "chore: auto-update ${{ matrix.lang }} SDK"
          branch: "auto-sdk-${{ matrix.lang }}"

8.2 Kiota:微软的现代化方案

Kiota是微软推出的新一代API客户端生成器,专注于类型安全和现代化:

# 安装
dotnet tool install --global Microsoft.OpenApi.Kiota

# 生成
kiota generate \
  --openapi ./openapi.yaml \
  --language python \
  --output ./sdk/python \
  --client-name MyApiClient

Kiota的优势在于与OpenAPI 3.1规范的更好兼容,以及与.NET生态的深度集成。

8.3 自建生成流水线(进阶)

如果你需要超越现有工具的定制化生成能力,可以基于Jinja2/Handlebars构建自己的流水线:

#!/usr/bin/env python3
"""自定义SDK生成器示例"""

import yaml
import json
from pathlib import Path
from jinja2 import Environment, FileSystemLoader

class SDKGenerator:
    def __init__(self, spec_path: str):
        with open(spec_path) as f:
            if spec_path.endswith('.yaml') or spec_path.endswith('.yml'):
                self.spec = yaml.safe_load(f)
            else:
                self.spec = json.load(f)
        
        self.env = Environment(
            loader=FileSystemLoader('./templates'),
            trim_blocks=True,
            lstrip_blocks=True
        )
    
    def resolve_ref(self, ref: str):
        """解析$ref引用"""
        parts = ref.lstrip('#/').split('/')
        result = self.spec
        for part in parts:
            result = result[part]
        return result
    
    def get_operations(self) -> list[dict]:
        """提取所有API操作"""
        operations = []
        for path, methods in self.spec.get('paths', {}).items():
            for method, details in methods.items():
                if method in ('get', 'post', 'put', 'patch', 'delete'):
                    operations.append({
                        'path': path,
                        'method': method.upper(),
                        'operation_id': details.get('operationId', f'{method}_{path}'),
                        'summary': details.get('summary', ''),
                        'parameters': details.get('parameters', []),
                        'request_body': details.get('requestBody'),
                        'responses': details.get('responses', {})
                    })
        return operations
    
    def get_models(self) -> list[dict]:
        """提取所有数据模型"""
        schemas = self.spec.get('components', {}).get('schemas', {})
        models = []
        for name, schema in schemas.items():
            models.append({'name': name, **schema})
        return models
    
    def generate_python_sdk(self, output_dir: str):
        """生成Python SDK"""
        operations = self.get_operations()
        models = self.get_models()
        
        template = self.env.get_template('python/client.py.j2')
        code = template.render(
            operations=operations,
            models=models,
            title=self.spec['info']['title']
        )
        
        output_path = Path(output_dir) / 'client.py'
        output_path.parent.mkdir(parents=True, exist_ok=True)
        output_path.write_text(code)
        print(f"Generated {output_path}")


if __name__ == '__main__':
    generator = SDKGenerator('./openapi.yaml')
    generator.generate_python_sdk('./sdk/python')

对应的Jinja2模板示例:

# templates/python/client.py.j2
"""{{ title }} - Auto-generated Python SDK"""
from __future__ import annotations
import httpx
from typing import Optional, overload
from dataclasses import dataclass


class {{ title | replace(' ', '') }}:
    """{{ title }} API Client"""
    
    def __init__(self, api_key: str, base_url: str = "https://api.example.com"):
        self._client = httpx.Client(
            base_url=base_url,
            headers={"Authorization": f"Bearer {api_key}"}
        )
    
    {% for op in operations %}
    def {{ op.operation_id }}(self{% for param in op.parameters %}, {{ param.name }}: {{ param | type_hint }}{% endfor %}):
        """
        {{ op.summary }}
        Method: {{ op.method }}
        Path: {{ op.path }}
        """
        response = self._client.{{ op.method.lower() }}(
            "{{ op.path | path_format }}"{% for param in op.parameters %},
            params={"{{ param.name }}": {{ param.name }}}{% endfor %}
        )
        response.raise_for_status()
        return response.json()
    
    {% endfor %}

8.4 MCP服务器手动构建最佳实践

在没有Stainless的情况下,构建高质量的MCP服务器需要遵循以下模式:

# 手动构建MCP服务器的最佳实践
from mcp.server.fastmcp import FastMCP
from pydantic import BaseModel, Field
from typing import Optional
import httpx

mcp = FastMCP(
    "my-api-server",
    instructions="Provides access to the MyAPI service"
)

# 使用Pydantic模型定义参数(替代OpenAPI Schema)
class SearchParams(BaseModel):
    query: str = Field(description="Search query string")
    limit: int = Field(default=10, ge=1, le=100, description="Max results")
    category: Optional[str] = Field(default=None, description="Filter by category")
    sort: str = Field(default="relevance", description="Sort order")

class SearchResult(BaseModel):
    id: str
    title: str
    url: str
    snippet: str

@mcp.tool()
async def search(
    query: str,
    limit: int = 10,
    category: Optional[str] = None,
    sort: str = "relevance"
) -> list[SearchResult]:
    """
    Search the API for matching results.
    
    Args:
        query: The search query
        limit: Maximum number of results (1-100)
        category: Optional category filter
        sort: Sort order (relevance, date, popularity)
    """
    params = SearchParams(
        query=query, limit=limit, category=category, sort=sort
    )
    
    async with httpx.AsyncClient() as client:
        resp = await client.get(
            "https://api.example.com/v1/search",
            params=params.model_dump(exclude_none=True)
        )
        resp.raise_for_status()
        data = resp.json()
        
        return [SearchResult(**item) for item in data["results"]]

# 带认证管理的MCP服务器
class AuthenticatedMCPServer(FastMCP):
    def __init__(self, *args, api_key: str, **kwargs):
        super().__init__(*args, **kwargs)
        self._api_key = api_key
        self._client = httpx.AsyncClient(
            base_url="https://api.example.com",
            headers={"Authorization": f"Bearer {api_key}"}
        )
    
    async def cleanup(self):
        await self._client.aclose()

# 注册资源(MCP Resources)
@mcp.resource("config://api-status")
def api_status() -> str:
    """Get the current API service status"""
    return "API is operational. Rate limit: 1000 req/min"

九、总结:AI时代的"基础设施战争"

Anthropic以超过22亿元人民币收购Stainless,是2026年AI行业最重要但最容易被低估的事件之一。

表面上看,这只是收购了一家"做SDK生成的公司"。但深入分析会发现:

1. 它是API基础设施层面的战略封锁。 当SDK自动生成成为AI公司的关键基础设施时,独占这个工具意味着获得持久的竞争优势。

2. MCP连接器是真正的战略资产。 在AI Agent时代,谁能最快地将API转化为AI可用的工具,谁就掌握了Agent生态的入口。Stainless的MCP生成能力是Anthropic独占的"API→AI工具"高速公路。

3. 开源替代方案存在但需要时间成熟。 OpenAPI Generator、Kiota等工具可以替代Stainless的SDK生成功能,但MCP服务器生成的自动化程度仍然不如Stainless。

4. 这预示着更广泛的趋势。 API基础设施正在成为AI战争的新前线。预计会有更多公司进入这个领域,也会出现更多类似的收购和竞争。

对于开发者而言,这次收购的教训是:

  • 不要过度依赖单一供应商的托管服务
  • API-first设计需要配套的自动化工具链
  • MCP协议是AI集成的未来,值得现在就投入学习
  • 基础设施的控制权之争,最终影响的是每一个开发者的日常体验

22亿人民币,买的不是一个工具,而是一个生态的入口钥匙。Anthropic押注的是:在AI Agent时代,工具的数量和质量比模型本身更重要。而这个赌注,可能真的会改变整个AI行业的格局。


本文写于2026年5月19日,基于公开报道和技术分析。文中代码示例基于Stainless生成SDK的公开输出特征进行分析还原。

复制全文 生成海报 Anthropic Stainless SDK MCP AI工具链 OpenAPI

推荐文章

Vue3中如何实现插件?
2024-11-18 04:27:04 +0800 CST
Vue 中如何处理跨组件通信?
2024-11-17 15:59:54 +0800 CST
Vue3中的Scoped Slots有什么改变?
2024-11-17 13:50:01 +0800 CST
程序员茄子在线接单