Skip to main content
Glama

list_posts

List recent stories published by a Medium user, defaulting to the authenticated user. Retrieve details like title and URL for content review.

Instructions

Read-only. List recent stories by a user (default: self).

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
limitNo
usernameNo

Implementation Reference

  • MediumClient.list_posts() - Core handler that lists recent stories by a user. Uses a hybrid approach: first tries RSS (zero-auth, fast), then falls back to GraphQL (needs sid). Supports source='auto' (default), 'rss', or 'graphql'. Resolves username from config or viewer profile if not provided.
    def list_posts(
        self,
        *,
        limit: int = 20,
        username: str | None = None,
        source: str = "auto",
    ) -> list[dict[str, Any]]:
        """List latest stories by a user (default: self).
    
        source:
          - "auto" (default): RSS first (zero-auth, fast); GraphQL fallback
            on miss/error or when limit > 10 (RSS only returns ~10).
          - "rss":  force RSS only.
          - "graphql": force GraphQL (needs sid).
        """
        username = (username or self.cfg.username or "").lstrip("@")
        if not username and (source == "auto" or source == "graphql"):
            try:
                viewer = self.get_my_profile()
                username = viewer.get("username") or ""
            except MediumAPIError:
                pass
        if not username:
            raise MediumAPIError(400, "no username to query (set MEDIUM_USERNAME or pass username=...)")
    
        if source in ("auto", "rss"):
            try:
                rss_posts = list_posts_via_rss(username, http=self.http, limit=limit)
                if source == "rss":
                    return [p.to_dict() for p in rss_posts]
                # auto: return RSS result if it satisfies `limit`, else fall
                # through to GraphQL for full pagination.
                if rss_posts and len(rss_posts) >= limit:
                    return [p.to_dict() for p in rss_posts][:limit]
            except Exception:
                if source == "rss":
                    raise
    
        data = self._gql(
            operation="UserStreamOverview",
            query="""
            query UserStreamOverview($username: ID!, $first: Int!) {
              user(username: $username) {
                id
                username
                postsConnection(first: $first) {
                  edges {
                    node {
                      id
                      title
                      uniqueSlug
                      mediumUrl
                      firstPublishedAt
                      clapCount
                      postResponses { count }
                    }
                  }
                }
              }
            }
            """,
            variables={"username": username, "first": limit},
        )
        edges = (((data.get("user") or {}).get("postsConnection") or {}).get("edges")) or []
        return [e["node"] for e in edges if e and e.get("node")][:limit]
  • MCP tool schema registration for 'list_posts' in the TOOLS dict - defines description, and input_schema with optional 'limit' (integer, default 20) and 'username' (string).
    "list_posts": {
        "description": (
            "Read-only. List recent stories by a user (default: self)."
        ),
        "input_schema": {
            "type": "object",
            "properties": {
                "limit": {"type": "integer", "default": 20},
                "username": {"type": "string"},
            },
        },
    },
  • Dispatch handler in _dispatch() that routes 'list_posts' calls to MediumClient.list_posts() with limit=20 default and optional username.
    if name == "list_posts":
        return c.list_posts(limit=args.get("limit", 20), username=args.get("username"))
  • list_posts_via_rss() - Helper function that fetches and parses Medium's RSS feed for a user, returning up to `limit` RssPost objects. Used as the zero-auth transport layer by the main handler.
    def list_posts_via_rss(
        username: str,
        *,
        http: httpx.Client | None = None,
        limit: int = 20,
    ) -> list[RssPost]:
        """High-level: fetch + parse, return up to `limit` posts."""
        xml = fetch_rss(username, http=http)
        return parse_rss(xml)[:limit]
Behavior2/5

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

The description only states 'Read-only' but does not elaborate on traits such as pagination, time window for 'recent', or any constraints. With no annotations provided, the burden falls on the description, which falls short.

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?

The description is extremely concise—only 7 words—and every word is meaningful. The 'Read-only' prefix is front-loaded for immediate safety signals. No wasted text.

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

Completeness2/5

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

Given the tool has 2 optional parameters, no output schema, and no annotations, the description is too brief. It lacks details on parameter semantics, result format, or behavioral constraints (e.g., rate limits, ordering).

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

Parameters1/5

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

The input schema has 2 parameters (limit, username) with 0% coverage in the description. The description adds no information about what these parameters control or their effects, forcing the agent to infer from defaults alone.

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 clearly states the action (list), the resource (recent stories), and scope (by a user, default self). It also adds 'Read-only' to indicate safe operation, distinguishing it from mutation tools.

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

Usage Guidelines2/5

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

While the description implies usage for listing recent stories of a specific user, it provides no explicit guidance on when to use this tool versus siblings like search_posts or get_feed. No when-not-to-use or alternatives mentioned.

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

Install Server

Other Tools

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/06ketan/medium-ops'

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