Skip to main content
Glama

http_request

Send HTTP requests using GET, POST, PUT, PATCH, or DELETE methods with custom headers and parameters. Returns full response data including status, headers, and body for API integration and web communication tasks.

Instructions

Execute an HTTP request with the specified method

Function/Features:

  • Sends HTTP requests using any standard method (GET, POST, PUT, PATCH, DELETE)

  • Allows custom HTTP headers

  • Returns complete HTTP response including status, headers, and body

Notes:

  • 'data' and 'json' parameters are mutually exclusive - use only one

  • When using 'json', the Content-Type header is automatically set to 'application/json'

  • When using 'data', you may need to set appropriate Content-Type header manually

  • Query parameters are URL-encoded automatically and appended to the URL

  • The response includes the full HTTP response with status line, all headers, and body

Args: url (str): Target URL for the HTTP request. method ('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'], optional): HTTP method to use. Defaults to "GET". query ({ [string]: string | number }, optional): Query parameters to append to the URL. Values are automatically converted to strings. Example: {'key1': 'value1', 'key2': 2}, becomes "key1=value1&key2=2" appended to the URL. headers ({ [string]: string }, optional): Custom HTTP request headers. data (str, optional): Text data to send in the request body. Cannot be used with 'json'. json (Any JSON, optional): Data to serialize as JSON and send in the request body. Cannot be used with 'data'.

Examples: // GET request (default method) http_request({url: "https://api.example.com/data"})

// GET request with query parameters http_request({url: "https://api.example.com/search", query: {"q": "test", "limit": 10}}) // POST request with JSON data http_request({url: "https://api.example.com/users", method: "POST", json: {"name": "John", "age": 30}}) // POST request with raw text data http_request({url: "https://api.example.com/log", method: "POST", data: "This is a log message"}) // PUT request http_request({url: "https://api.example.com/users/123", method: "PUT", json: {"name": "John Updated", "age": 31}}) // PATCH request http_request({url: "https://api.example.com/users/123", method: "PATCH", json: {"age": 31, "email": "new@example.com"}}) // DELETE request http_request({url: "https://api.example.com/users/123", method: "DELETE"}) // Request with custom headers http_request({url: "https://api.example.com/secure", method: "POST", headers: {"Authorization": "Bearer token"}, json: {"key": "value"}})

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
urlYes(require) Target URL for the HTTP request
methodYes(optional, Defaults to "GET") HTTP method to use for the request
queryYes
headersYes
dataYes
jsonYes

Implementation Reference

  • Primary MCP tool handler for 'http_request'. Includes registration via @mcp.tool(), input schema via Annotated types, and execution logic calling mcp_http_request with user-agent and formatting.
    @mcp.tool() def http_request( url: Annotated[str, "(require) Target URL for the HTTP request"], *, method: Annotated[Literal['GET', 'POST', 'PUT', 'PATCH', 'DELETE'], "(optional, Defaults to \"GET\") HTTP method to use for the request"] = "GET", query: Annotated[Optional[Dict[str, str | int | float]], "(optional) Query parameters to append to the URL"] = None, headers: Annotated[Optional[Dict[str, str]], "(optional) Custom HTTP request headers"] = None, data: Annotated[Optional[str], "(optional) Text data to send in the request body. Cannot be used with 'json'"] = None, json: Annotated[Optional[Any], "(optional) JSON to send in the request body. Cannot be used with 'data'"] = None, ) -> str: """Execute an HTTP request with the specified method Function/Features: - Sends HTTP requests using any standard method (GET, POST, PUT, PATCH, DELETE) - Allows custom HTTP headers - Returns **complete** HTTP response including status, headers, and body Notes: - 'data' and 'json' parameters are mutually exclusive - use only one - When using 'json', the Content-Type header is automatically set to 'application/json' - When using 'data', you may need to set appropriate Content-Type header manually - Query parameters are URL-encoded automatically and appended to the URL - The response includes the full HTTP response with status line, all headers, and body Args: url (str): Target URL for the HTTP request. method ('GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE'], optional): HTTP method to use. Defaults to "GET". query ({ [string]: string | number }, optional): Query parameters to append to the URL. Values are automatically converted to strings. Example: {'key1': 'value1', 'key2': 2}, becomes "key1=value1&key2=2" appended to the URL. headers ({ [string]: string }, optional): Custom HTTP request headers. data (str, optional): Text data to send in the request body. Cannot be used with 'json'. json (Any JSON, optional): Data to serialize as JSON and send in the request body. Cannot be used with 'data'. Examples: // GET request (default method) http_request({url: "https://api.example.com/data"}) // GET request with query parameters http_request({url: "https://api.example.com/search", query: {"q": "test", "limit": 10}}) // POST request with JSON data http_request({url: "https://api.example.com/users", method: "POST", json: {"name": "John", "age": 30}}) // POST request with raw text data http_request({url: "https://api.example.com/log", method: "POST", data: "This is a log message"}) // PUT request http_request({url: "https://api.example.com/users/123", method: "PUT", json: {"name": "John Updated", "age": 31}}) // PATCH request http_request({url: "https://api.example.com/users/123", method: "PATCH", json: {"age": 31, "email": "new@example.com"}}) // DELETE request http_request({url: "https://api.example.com/users/123", method: "DELETE"}) // Request with custom headers http_request({url: "https://api.example.com/secure", method: "POST", headers: {"Authorization": "Bearer token"}, json: {"key": "value"}}) """ return mcp_http_request(method, url, query=query, data=data, json=json, headers=headers, user_agent=ua, force_user_agnet=ua_force)
  • Intermediate wrapper mcp_http_request: adds User-Agent header, calls core http_request, formats response or error.
    def mcp_http_request( method: str, url: str, *, query: Optional[dict] = None, data: Optional[str | bytes | bytearray] = None, json: Optional[dict] = None, headers: Optional[dict] = None, user_agent: Optional[str] = None, force_user_agnet: Optional[bool] = None, format_status: bool = True, format_headers: bool = True, return_content: Literal['raw', 'basic_clean', 'strict_clean', 'markdown'] = "raw", ) -> str: hs = {} if headers: hs.update(headers) if force_user_agnet: if user_agent: hs["User-Agent"] = user_agent else: if "User-Agent" not in hs and user_agent: hs["User-Agent"] = user_agent try: response = http_request( method, url, query=query, headers=hs, data=data, json_=json ) return format_response_result( response, format_status=format_status, format_headers=format_headers, return_content=return_content ) except Exception as e: return format_error_result(e)
  • Core low-level http_request implementation using Python's urllib.request. Handles URL/query, data/json body, headers, returns Response object. Includes error cases.
    def http_request( method: str, url: str, *, query: Optional[dict] = None, data: Optional[Union[str, bytes, bytearray]] = None, json_: Optional[dict] = None, headers: Optional[dict] = None ) -> Response: if headers is None: headers = {} if not isinstance(method, str): raise ArgumentError(f"http method must be a string, and must be one of {str(HTTP_METHODS)}") m, method = method, method.upper() if method not in HTTP_METHODS: raise ArgumentError(f"Invalid HTTP method: {m}, must be one of {str(HTTP_METHODS)}") if not isinstance(url, str): raise ArgumentError("URL must be a string") if data is not None and json_ is not None: raise ArgumentError("Both data and json cannot be provided at the same time") try: if query is not None: url = merge_query_to_url(url, query) except ArgumentError as e: raise e from e except Exception as e: raise ArgumentError("Failed to splicing URL and query") from e data_bytes = None if data is not None: if not isinstance(data, (str, bytes, bytearray)): raise ArgumentError("Data must be a string, bytes, or bytearray") elif isinstance(data, str): data_bytes = data.encode(encoding="utf-8") elif isinstance(data, bytearray): data_bytes = bytes(data) else: data_bytes = data elif json_ is not None: try: data_bytes = json.dumps(json_).encode(encoding="utf-8") except Exception as e: raise ArgumentError("Failed to serialize JSON data") from e if not url.startswith("http://") and not url.startswith("https://"): url = "https://" + url try: url = quote(url, safe=";/?:@&=+$,", encoding="utf-8") request = urllib.request.Request(url, method=method, headers=headers, data=data_bytes) response: http.client.HTTPResponse = urllib.request.urlopen(request) version = VERSION_MAP.get(response.version, "HTTP/1.1") status_code = response.status reason = response.reason response_headers = response.getheaders() content = response.read() result = Response(url, version, status_code, reason, response_headers, content) except urllib.error.HTTPError as e: if e.status is None: raise RequestError(f"Failed to send request, unknown error") from e version = "HTTP/1.1" status_code = e.status reason = e.reason response_headers = e.headers.items() content = e.read() result = Response(url, version, status_code, reason, response_headers, content) except urllib.error.URLError as e: raise RequestError(f"Failed to send request, {e.reason}") from e except Exception as e: raise RequestError(f"Failed to send request, {e}") from e return result
  • Response dataclass schema defining the structure of HTTP response objects used throughout the tool.
    @dataclass class Response: url: str version: str status_code: int reason: str headers: list[tuple[str, str]] content: str | bytes | bytearray _content_type: str | None = None @property def content_type(self) -> str: if self._content_type is None: for k, v in self.headers: if k.lower() == "content-type": self._content_type = v if self._content_type is None: self._content_type = "application/octet-stream" return self._content_type
  • Helper to format the final response string: handles content decoding, HTML cleaning/markdown conversion, assembles status/headers/body.
    def format_response_result( response: Response, *, format_status: bool | None = None, format_headers: bool | None = None, return_content: Literal["raw", "basic_clean", "strict_clean", "markdown"] = "raw", ) -> str: http_version = response.version status = response.status_code reason = response.reason headers = response.headers content = response.content content_type = response.content_type if not isinstance(content_type, str): content_type = 'application/octet-stream' if content_type.startswith("text/") or content_type.startswith("application/json"): try: if isinstance(content, (bytes, bytearray)): content = content.decode('utf-8') else: content = str(content) except UnicodeDecodeError as e: err_message = f"response content type is \"{content_type}\", but not utf-8 encoded'" raise ResponseError(response, err_message) from e except Exception as e: err_message = f"response content type is \"{content_type}\", but cannot be converted to a string" raise ResponseError(response, err_message) from e else: err_message = f'response content type is "{content_type}", cannot be converted to a string' raise ResponseError(response, err_message) if content_type.startswith("text/html"): if return_content == "raw": pass elif return_content == "basic_clean": content = clean_html(content, allowed_attrs=True) elif return_content == "strict_clean": content = clean_html(content, allowed_attrs=("id", "src", "href")) elif return_content == "markdown": content = html_to_markdown(content) strs = [] if format_status: strs.append(f"{http_version} {status} {reason}\r\n") if format_headers: response_header_str = "\r\n".join(f"{k}: {v}" for k, v in headers) strs.append(response_header_str) if len(strs) > 0: strs.append("\r\n\r\n") strs.append(content) return "\r\n".join(strs)

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/coucya/mcp-server-requests'

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