We built git blame for AI agents – here’s how it works

Your team uses Claude Code, Cursor, or Gemini to write code. 60-80% of new commits are AI-generated.

But when a bug appears – can you answer: which AI wrote this line?

We built Origin to solve this. Here’s how it works under the hood.

The problem

Traditional git blame shows who committed code. But when your whole team uses AI agents, “who committed” is always the developer — even when Claude wrote 90% of the file.

You lose:

• which agent generated the code
• what prompt produced it
• what model was used
• what it cost

How Origin tracks it

Every time an AI agent starts a session, Origin hooks fire:

# Claude Code hooks (auto-installed via origin init)
origin hooks claude-code session-start
origin hooks claude-code user-prompt-submit
origin hooks claude-code stop

When a commit happens, Origin writes session data to git notes:

git notes show HEAD
# Origin-Session: abc123
# Agent: claude-code
# Model: claude-opus-4-6
# Cost: $2.40
# Prompts: 12

AI Blame

Now you can see who wrote every line:

origin blame src/api.ts

Line  Tag  Model              Content
────────────────────────────────────────
1     [HU]                   import express from 'express'
2     [AI] claude-opus-4-6   const app = express()
3     [AI] claude-opus-4-6   app.use(express.json())
4     [HU]                   // my custom middleware

Retroactive attribution

Already have a repo with months of AI commits but no tracking?

origin backfill --apply

Origin analyzes commit message patterns, author emails, and code style to detect which commits were AI-generated — even without hooks.

Policy enforcement

Origin also enforces rules before commits land:

# Block commits containing secrets
# Block commits to restricted files
# Enforce budget limits per agent

Pre-commit hook fetches active policies from your Origin dashboard and blocks violations before they hit the repo.

Try it

npm i -g https://getorigin.io/cli/origin-cli-latest.tgz
origin init

Works with Claude Code, Cursor, Gemini CLI, Codex. Data stored in git notes — no server required for standalone mode.

Open source CLI: https://github.com/dolobanko/origin-cli
Team dashboard: https://getorigin.io

12 DevOps Tools You Should Be Using in 2026 (SREs Included)

Upright

When everything online carries an “AI-powered” label and fatigue sets in, this curated list offers twelve practical DevOps and SRE solutions. The focus is infrastructure, security, observability, and incident management—mostly open-source, zero chatbots.

Table of Contents

  • Monitoring & Observability
  • Incident Management & Alerting
  • Infrastructure & Application Platform
  • Security
  • Dev Tools & Diagramming

Monitoring & Observability

Upright

Upright

Basecamp’s open-source synthetic monitoring system runs health checks across multiple geographic locations, reporting metrics through Prometheus without vendor lock-in.

The platform supports standard HTTP checks alongside Playwright-based browser automation for end-to-end transaction testing. Probes are defined via YAML or Ruby classes, scheduled across distributed nodes, with results feeding directly into Prometheus/AlertManager. Built using Rails, SQLite, and Kamal deployment.

Upright Github Repo (707 ⭐s) →

HyperDX

HyperDX

Built on ClickHouse and OpenTelemetry, this open-source observability platform consolidates logs, metrics, traces, errors, and session replays into one self-hostable interface—comparable to Datadog but self-managed.

ClickHouse’s columnar storage efficiently handles high-cardinality data. Full-text search combined with property filtering works without SQL knowledge. Built on OpenTelemetry standards, so existing OTEL data integrates directly. Most features use MIT licensing; managed cloud runs on ClickHouse Cloud.

HyperDX Github Repo (7,400 ⭐s) →

Incident Management & Alerting

Keep

Keep

An open-core AIOps alert management platform that integrates with existing monitoring stacks (Grafana, Datadog, PagerDuty) to correlate, deduplicate, and route alerts without replacing current tools.

Integration-first design connects via bidirectional integrations. Alert enrichment and suppression rules operate across your entire stack. Routing uses Python or YAML; AI correlation groups alerts using historical incident context. Self-hosted path is open source; managed service offers paid tiers above free.

Keep Github Repo (5,900 ⭐s) →

OpenStatus

OpenStatus

An open-core uptime monitoring and status page platform with probes running from 28 regions across Fly.io, Koyeb, and Railway simultaneously.

Multi-provider probe architecture avoids the blind spot where monitors live on identical infrastructure as monitored services. Private monitoring locations via 8.5MB Docker images check internal services behind firewalls. Supports terminal-based monitoring configuration and CI/CD integration. Notifications route through Slack, Discord, PagerDuty, email, and webhooks. Self-hosted version is fully open source (AGPL-3.0); managed service includes free and paid tiers.

OpenStatus Github Repo (8,500 ⭐s) →

Infrastructure & Application Platform

Unregistry

Unregistry

An open-source utility enabling direct Docker image pushing to remote servers over SSH—eliminating Docker Hub, ECR, or registry infrastructure requirements.

The mechanism uses a fake registry protocol on one end while streaming layers directly to target servers via SSH. From Docker’s perspective, standard pushing occurs; images land remotely without intermediate storage. Ideal for small-to-medium deployments on dedicated servers or VPS where registry overhead feels excessive.

Unregistry Github Repo (4,656 ⭐s) →

Edka

Edka

A managed service provisioning and operating Kubernetes clusters on your Hetzner Cloud account while preserving infrastructure ownership and billing control.

Edka manages control planes, add-ons, and day-two operations. You get managed Kubernetes at Hetzner pricing without EKS, GKE, or AKS infrastructure premiums or cluster maintenance burden. The platform provides PaaS-like experiences: git-push deployments, one-click add-ons (cert-manager, metrics-server, CloudNativePG), and preview environments. Closed source with SaaS pricing.

Edka Website →

Enroll

Enroll

This open-source tool SSH’s into live servers and reverse-engineers current configurations into Ansible playbooks and roles—useful for bootstrapping infrastructure-as-code on manually configured systems.

It captures installed packages, running services, modified files, and configuration typically residing only in memory or documentation. Output comprises Ansible roles suitable for version control and server state reproduction. For infrastructure predating automation practices, this approach enables controlled management without complete rebuilds.

Enroll Website →

Canine

Canine

An open-source, Kubernetes-native PaaS recreating the Heroku developer experience on your own cluster—git-push deployments, review applications, managed add-ons, and dashboards without abstraction layers hiding Kubernetes primitives.

Targets teams wanting developer-friendly workflows without Heroku expenses or fully managed PaaS opacity. Running on personal clusters provides Heroku UX while maintaining direct kubectl and Kubernetes API access. Add-ons provision as standard Kubernetes resources rather than opaque services.

Canine Github Repo (2,783 ⭐s) →

Security

Pangolin

Pangolin

An open-source, self-hostable tunneling server and reverse proxy serving as a Cloudflare Tunnels alternative for exposing private services without public IPs or open inbound ports.

Architecture mirrors Cloudflare Tunnels: lightweight agents establish outbound connections to Pangolin instances, which handle TLS termination and inbound request routing. The distinction: you operate the tunnel server, so traffic never crosses third-party infrastructure. Nearly 20,000 GitHub stars demonstrate team appetite for convenience without trust dependencies.

Pangolin Github Repo (19,230 ⭐s) →

Octelium

Octelium

An open-source zero-trust access platform consolidating four typically separate tools into one self-hostable stack: Teleport (infrastructure access), Cloudflare Access (application proxying), Tailscale (network connectivity), and Ngrok (tunneling).

Consolidation eliminates overlapping policies, fragmented audit logs, and multiple agent maintenance. Octelium handles SSH/RDP access, HTTP application proxying, private network tunneling, and identity-aware policy enforcement with unified audit trails. Over 3,400 stars for this newer project validate zero-trust consolidation appeal.

Octelium Github Repo (3,421 ⭐s) →

Dev Tools & Diagramming

IcePanel

IcePanel

A collaborative architecture diagramming tool structured around the C4 model—System Context, Container, Component, and Code hierarchy providing distributed system diagrams with shared grammar.

Unlike Miro or Lucidchart, IcePanel employs model-first rather than drawing-first approaches. Objects defined once reuse across diagrams; updating service names or dependencies cascades automatically everywhere. For teams experiencing architecture documentation drift, this single-source-of-truth constraint delivers real value. Closed source and SaaS-exclusive.

IcePanel Website →

Witr

Witr

An open-source CLI tool answering a fundamental question: why is this process running? Given a PID or process name, it traces parent chains, resolves responsible systemd units, and follows startup scripts to origins.

During incidents, quickly discovering what spawned unexpected production processes saves time. Witr handles common scenarios: systemd-initiated processes, cron jobs, init scripts, and container entrypoints—displaying chains in readable trees. Practical for incident investigation runbooks.

Witr Github Repo (13,480 ⭐s) →

Conclusion

DevOps tooling need not be complex. The most valuable tools quietly solve specific operational problems and remain unobtrusive.

This collection likely includes at least one tool worth integrating into your workflow. Share your favorite 2026 DevOps and SRE tools at [email protected]. 🚀

We Gave LLMs 150 Tools: Here’s What Broke.

Accuracy vs toolset size across 6 LLMs

There’s a hypothesis that most people building AI agents have encountered but few have measured: the more tools you give an LLM, the worse it gets at picking the right one.

It’s intuitive. Connect a few MCP servers to your agent, and suddenly it’s choosing from 60, 80, 100+ tools. GitHub tools, GitLab tools, Kubernetes, Slack, Jira, PagerDuty, Terraform, Grafana, all loaded into the context window, all the time. The model has to read every tool definition, understand the distinctions between them, and pick the right one. That’s a lot of signal to sift through.

But intuition isn’t data. So we built Boundary, an open-source framework for finding where LLM context breaks, and ran the numbers.

The setup

We assembled 150 tool definitions based on real schemas from production agent systems across 16 services: GitHub, GitLab, Jira, Confluence, Kubernetes, AWS, Datadog, Slack, PagerDuty, Okta, Snyk, Grafana, Terraform Cloud, Docker, Linear, and Notion. The tools are synthetic (no-op for benchmarking) but the schemas, parameter structures, and descriptions mirror what you’d find in a production MCP environment.

We tested six models across three providers:

  • Claude Sonnet 4.6 and Claude Haiku 4.5 (Anthropic)
  • GPT-4o and GPT-5.4 Mini (OpenAI)
  • Grok 4 and Grok 4.1 Fast Reasoning (xAI)

Each model received 60 prompts (both direct requests and ambiguous ones) at five toolset sizes: 25, 50, 75, 100, and 150 tools. At each size, the available tools were randomly selected but always included the correct one. The question: does the model pick the right tool?

The results

Every model that completed the test degraded. Two didn’t finish at all.

Model 25 tools 50 tools 75 tools 100 tools 150 tools
Grok 4.1 Fast 86.7% 83.3% 80.0% 83.3% 76.7%
GPT-5.4 Mini 85.0% 85.0% 80.0% 83.3% failed
GPT-4o 81.7% 78.3% 73.3% 76.7% failed
Claude Haiku 4.5 81.7% 80.0% 78.3% 80.0% 76.7%
Grok 4 80.0% 78.3% 80.0% 71.7% 80.0%
Claude Sonnet 4.6 78.3% 73.3% 73.3% 76.7% 75.0%

Accuracy vs toolset size across 6 LLMs

GPT-5.4 Mini was the most surprising result. At 85% accuracy through 50 tools, 92% on ambiguous prompts, sub-1-second latency, and $0.002 per call, it was arguably the best overall performer for small-to-medium toolsets. Then it hit the same 128-tool wall as GPT-4o and failed completely at 150.

Grok 4.1 Fast Reasoning was the only model that combined top-tier accuracy with the ability to handle 150 tools. It degraded steadily from 86.7% to 76.7%, but it never broke.

Both OpenAI models failed at 150 tools. OpenAI’s API has a hard limit of 128 tools per request. This isn’t a degradation curve. It’s a wall. If your agent connects enough MCP servers to exceed 128 tools, no OpenAI model works.

Claude Sonnet 4.6, the most expensive model in the test ($0.028/call), was the least accurate at 25 tools and never recovered. Claude Haiku outperformed it at every size while costing 3x less.

Cross-service confusion scales with tools

Cross-service confusion, where a model picks a tool from the wrong service entirely, was the most dangerous failure mode.

Model 25 tools 50 tools 75 tools 100 tools 150 tools
Claude Haiku 4.5 0 0 1 2 4
Grok 4.1 Fast 0 0 0 2 3
Claude Sonnet 4.6 0 1 2 3 2
Grok 4 2 0 2 4 1
GPT-4o 0 0 1 2 n/a
GPT-5.4 Mini 0 0 2 1 n/a

Grok 4 had cross-service errors even at 25 tools. Claude Haiku was clean until 75 tools but escalated to 4 errors at 150, the worst of any model at that size.

The most common cross-service confusions across all models:

  • Datadog vs Grafana: “Check the monitoring alerts” consistently routed to the wrong observability platform
  • Notion vs Confluence: “Search for documentation” split between the two
  • Linear vs Jira: “Add a comment to the tracking issue” picked the wrong project tracker
  • GitHub vs GitLab: “Show me the open issues” confused the two at higher tool counts

Direct vs. ambiguous prompts

A “direct” prompt names the service: “List all Terraform Cloud workspaces.” An “ambiguous” prompt doesn’t: “Add a comment saying ‘Resolved’ to the tracking issue.”

Model 25t (ambig) 50t (ambig) 75t (ambig) 100t (ambig) 150t (ambig)
GPT-5.4 Mini 92% 92% 67% 92% n/a
Grok 4.1 Fast 83% 83% 83% 75% 67%
Claude Sonnet 4.6 83% 75% 75% 83% 75%
GPT-4o 83% 83% 67% 58% n/a
Claude Haiku 4.5 75% 75% 83% 67% 67%
Grok 4 67% 75% 67% 50% 67%

GPT-5.4 Mini dominated ambiguous prompts at 92% through 100 tools. It handled disambiguation better than any other model by a wide margin. GPT-4o collapsed to 58% at the same size. Grok 4 hit 50%, a coin flip.

Claude Sonnet was the most stable, staying between 75% and 83% regardless of toolset size. Consistent, but never great.

Where models get confused

The errors tell a story. Some patterns appeared across all six models:

Terraform is hard. All models consistently confused terraform_create_run with terraform_list_workspaces, and terraform_lock_workspace with terraform_get_workspace. The tool names are semantically close, and the models default to “list” or “get” operations when the toolset is crowded.

Snyk is a trap. snyk_get_remediation, snyk_list_container_projects, and snyk_list_projects all got misrouted to snyk_list_organizations. When Snyk tools are buried among 100+ others, the models default to the most generic-sounding option.

Confluence updates fail. All models picked confluence_search when asked to update a page. The prompt said “Update the runbook page”, but with 75+ tools in context, the model reached for search instead of the update operation.

Monitoring platform confusion. Datadog and Grafana both have alerting, dashboards, and metrics tools. The prompt “Check the monitoring alerts for the API server” got routed to Grafana instead of Datadog by every model at some toolset size. Adding two similar services to the toolset creates permanent ambiguity.

The latency story

Accuracy isn’t the only cost.

Model 25 tools 50 tools 75 tools 100 tools 150 tools
GPT-5.4 Mini 739ms 754ms 849ms 976ms n/a
GPT-4o 1,170ms 4,035ms 6,213ms 7,657ms n/a
Claude Haiku 4.5 2,463ms 6,157ms 8,765ms 11,473ms 16,749ms
Claude Sonnet 4.6 4,728ms 10,308ms 14,579ms 19,120ms 27,935ms
Grok 4.1 Fast 6,448ms 7,042ms 6,930ms 7,349ms 7,533ms
Grok 4 7,706ms 7,945ms 8,133ms 8,418ms 9,552ms

Latency vs toolset size

GPT-5.4 Mini was the latency champion: sub-1-second at every toolset size it completed. The Anthropic models scaled linearly, with Sonnet reaching 28 seconds at 150 tools. The xAI models barely changed, staying in the 6-10 second range regardless of tool count.

What this means

The pattern is consistent across six models from three providers: more tools means worse accuracy, and the degradation starts between 25 and 50 tools.

The implications for anyone building agents with MCP:

  1. Don’t load everything. If your agent has access to 10+ services, that’s easily 80-150 tools. Loading them all upfront is a measurable tax on accuracy, starting at 25 tools.

  2. OpenAI has a hard wall at 128 tools. Both GPT-4o and GPT-5.4 Mini failed at 150. This isn’t a model quality issue. It’s a platform constraint. If your agent might exceed 128 tools, OpenAI models are not an option.

  3. Ambiguous prompts are the danger zone. Grok 4 hit 50% accuracy on ambiguous prompts at 100 tools. GPT-4o dropped to 58%. When users don’t name the service explicitly, the model has to disambiguate, and more tools makes that exponentially harder.

  4. Similar services compound the problem. Datadog and Grafana. Notion and Confluence. Linear and Jira. GitHub and GitLab. Every pair of similar services in the toolset creates a permanent source of confusion that scales with tool count.

  5. Latency compounds. Even if accuracy were flat, the latency cost matters. Claude Sonnet at 28 seconds per call is unusable for interactive workloads. GPT-5.4 Mini at sub-1-second is a different product entirely.

  6. Price does not predict performance. Claude Sonnet 4.6 costs 28x more per call than Grok 4.1 Fast and is less accurate. Claude Haiku outperforms Claude Sonnet at 3x lower cost. The most expensive model lost.

The cost equation

What you pay per call versus what you get in accuracy.

Model Total cost Calls Cost/call Best accuracy Worst accuracy
Grok 4.1 Fast $0.31 300 $0.0010 86.7% (25t) 76.7% (150t)
GPT-5.4 Mini $0.50 240* $0.0021 85.0% (25t) failed (150t)
GPT-4o $1.57 240* $0.0065 81.7% (25t) failed (150t)
Claude Haiku 4.5 $2.83 300 $0.0094 81.7% (25t) 76.7% (150t)
Grok 4 $3.85 300 $0.013 80.0% (25t) 71.7% (100t)
Claude Sonnet 4.6 $8.51 300 $0.028 78.3% (25t) 73.3% (50t)

*OpenAI models completed 240 of 300 calls. All calls at 150 tools failed due to the 128-tool API limit.

Cost vs accuracy tradeoff

The two cheapest models (Grok 4.1 Fast at $0.001/call and GPT-5.4 Mini at $0.002/call) were also the two most accurate. The most expensive model (Claude Sonnet at $0.028/call) was the least accurate. The correlation between price and tool-calling performance is not just weak. It’s inverted.

This is exactly the kind of tradeoff Boundary is designed to surface. Without benchmark data, you’d likely pick Claude Sonnet or GPT-4o. The data says they’re among the worst choices for tool-calling workloads. A team running fewer than 128 tools should seriously consider GPT-5.4 Mini for its combination of accuracy, speed, and cost. A team that might exceed 128 needs Grok 4.1 Fast or an Anthropic model.

Running these benchmarks costs almost nothing. This entire run across six models cost $17. That’s less than a single hour of engineer time debugging a misrouted tool call in production.

How this shaped our architecture

This data isn’t theoretical for us. It directly informed how we built progressive disclosure in SixDegree.

The core insight: if accuracy degrades between 25 and 50 tools, then the goal isn’t to find a smarter model. It’s to never present more than 25 tools in the first place. Not by hardcoding a curated list, but by letting the agent’s context determine which tools are relevant at each step.

In SixDegree, when an agent queries the ontology and discovers a GitHub repository, only the GitHub tools become available. When a Kubernetes deployment surfaces through a relationship, the Kubernetes tools appear. The agent never sees all 150 tools at once because it never needs to. The toolset at any given turn is scoped to the entities the agent has actually encountered.

The Boundary data validates this approach quantitatively. At 25 tools (roughly the size of two or three services’ worth of tools), accuracy is in the mid-to-high 80s. That’s the operating range progressive disclosure keeps you in, regardless of how many total services are connected. You can have 16 integrations and 150 tools installed, and the agent still only sees the 10-20 that matter for the current conversation.

The alternative, loading everything and hoping the model figures it out, costs you 5-10 percentage points of accuracy, up to 28x the latency, and for OpenAI models, a hard failure at 128 tools. Progressive disclosure isn’t a nice-to-have. It’s a requirement for agents that work at scale.

Limitations and what we’d like to improve

This benchmark is a starting point, not a definitive answer. There are real limitations to what it measures and how:

Single-turn only. Each prompt gets one shot at picking a tool. Real agents chain tool calls, use results from previous calls to inform the next one, and recover from mistakes. A model that picks the wrong tool on the first try might self-correct on a second turn. This benchmark doesn’t capture that.

Random tool subsets. At each toolset size, the available tools are randomly selected (with the correct one always included). In production, the tools in context aren’t random. They’re usually grouped by service or use case. Random selection may overstate or understate confusion depending on which tools end up adjacent.

No parameter validation. We check whether the model picked the right tool, but not whether it filled in the parameters correctly. A model that picks github_create_issue but hallucinates the owner field is still counted as correct. Parameter accuracy is a whole separate dimension.

Prompt quality varies. Some of the ambiguous prompts have arguably debatable expected answers. “Check the monitoring alerts” could reasonably map to either Datadog or Grafana depending on the organization. We picked one, but reasonable people would disagree.

Single trial. Each prompt runs once per toolset size. With 60 prompts per size, the results are directional but individual percentage points could shift with more trials.

We’d like to add multi-turn evaluation, parameter accuracy checking, configurable prompt difficulty levels, and more models. If you have ideas for how to make this benchmark better, if you disagree with our methodology, or if you’ve run Boundary against a model we haven’t tested yet, open an issue or submit a PR. This is an open source project and we want the community to help shape it.

What’s next

The full interactive results from this run are available on our site. The framework is open source. Run it yourself and see how your preferred models handle tool overload.

Boundary is an open-source framework for finding where LLM context breaks. See how SixDegree solves tool overload.

Gemini Live, Gemini 3.1 Flash Live ile güncellendi

Gemini Live, Gemini 3.1 Flash Live ile güncellendi

Gemini Live, Gemini 3.1 Flash Live ile güncellendiGoogle, Gemini Live’ın yeni geliştirilen Gemini 3.1 Flash Live yapay zeka modeliyle güncellendiğini duyurdu. Live’ın şimdiye kadarki en büyük güncellemesini aldığını aktaran şirket, yeni altyapıda kullanıcıların daha az duraksama ile çok daha hızlı ve akıllı cevaplar alabileceğini, sistemin artık genel akışı bozmadan iki kat daha uzun sohbet takibi gerçekleştirebildiğini ve Live’ın artık cevapların uzunluğu ile tonunu o anki duruma göre otomatik olarak ayarlayabildiğini belirtti. Google bunlara ek olarak Gemini 3.1 Flash Live’ın bugün Search Live için de devreye alındığını açıkladı. Bu altyapı yapay zeka modunun (AI Modu) açık olduğu tüm ülkelerde aktif edildi. Gemini Live just got its biggest upgrade yet, powered by Gemini 3.1 Flash Live. •Faster responses with fewer awkward pauses•Smarter & able to follow along 2x longer conversations, so you can stay in the flow•Dynamically adjusts its answer lengths & tone to match the moment pic.twitter.com/b4YaJi3W7a — Google Gemini (@GeminiApp) March 26, 2026

Gemini Live, Gemini 3.1 Flash Live ile güncellendi yazısı ilk olarak Teknoloji haberleri – LOG üzerinde yayınlandı.

Wikipedia, yapay zeka üretimi içerikleri yasakladı

Wikipedia

WikipediaWikipedia, bugün yaptığı açıklama ile yapay zeka üretimi içerikleri ve mevcut içeriklerin yapay zeka yardımıyla yeniden yazılmasını yasakladığını duyurdu. Editörlerin yapay zeka sistemlerinden yardım alarak temel düzenlemeler ve dil/sayfa/içerik çevirileri yapmasına (İngilizce) izin veren platform, doğrudan yapay zeka yardımıyla içerik üretilmesini ise kesinlikle istemiyor. Editörler, platforma eklenen yapay zeka üretimi içerikleri oldukça uzun zamandır eleştiriyor. Hatta yapay zeka imzalı içeriklerle mücadele etmek ve platforma katkı sağlayanların bu içerikleri tespit etmesine yardımcı olmak amacıyla WikiProject AI Cleanup adlı bir girişim dahi başlatılmıştı.

Wikipedia, yapay zeka üretimi içerikleri yasakladı yazısı ilk olarak Teknoloji haberleri – LOG üzerinde yayınlandı.

Web3 Automation with Python: From Zero to Daily NFT Mints

As a developer, I’ve always been fascinated by the potential of Web3 and its applications. Recently, I embarked on a journey to automate Web3 tasks using Python, and I’m excited to share my experience with you. In this article, I’ll take you through the process of creating a Python script that automates daily NFT mints on the Ethereum blockchain. # Introduction to Web3 Automation Web3 automation refers to the use of software to automate tasks on the blockchain. This can include tasks such as sending transactions, interacting with smart contracts, and minting NFTs. Python is an ideal language for Web3 automation due to its simplicity, flexibility, and extensive libraries. # Setting Up the Environment Before we dive into the code, let’s set up our environment. You’ll need to install the following libraries: * web3: a Python library for interacting with the Ethereum blockchain * json: a library for working with JSON data You can install these libraries using pip:

python import json from web3 import Web3

# Connecting to the Ethereum Blockchain To connect to the Ethereum blockchain, you’ll need to set up a provider. A provider is an API that allows you to interact with the blockchain. You can use a provider like Infura or Alchemy. For this example, I’ll use Infura.

python w3 = Web3(Web3.HTTPProvider('https://mainnet.infura.io/v3/YOUR_PROJECT_ID'))

Replace YOUR_PROJECT_ID with your actual Infura project ID. # Creating an NFT Minting Script Now that we have our environment set up, let’s create a script that mints an NFT on the Ethereum blockchain. We’ll use the web3 library to interact with the blockchain and the json library to work with JSON data.

python def mint_nft(token_name, token_symbol, token_uri): contract_address = '0x...CONTRACT_ADDRESS...' contract_abi = json.loads('...CONTRACT_ABI...') contract = w3.eth.contract(address=contract_address, abi=contract_abi) tx_hash = contract.functions.mintNFT(token_name, token_symbol, token_uri).transact() return tx_hash

Replace ...CONTRACT_ADDRESS... and ...CONTRACT_ABI... with your actual contract address and ABI. # Scheduling the Script to Run Daily To schedule the script to run daily, you can use a scheduler like schedule or apscheduler. For this example, I’ll use schedule.

python import schedule import time def job(): mint_nft('My NFT', 'MNFT', 'https://example.com/metadata.json') schedule.every().day.at('08:00').do(job) while True: schedule.run_pending() time.sleep(1)

This script will run the mint_nft function every day at 8:00 AM. # Conclusion In this article, we’ve created a Python script that automates daily NFT mints on the Ethereum blockchain. We’ve set up our environment, connected to the blockchain, created an NFT minting script, and scheduled the script to run daily. With this script, you can automate your Web3 tasks and focus on more important things. Remember to replace the placeholders with your actual contract address, ABI, and Infura project ID. Happy coding!

How I Used Notion MCP to Build an Autonomous Personal Finance Tracker

FinanceIQ — AI-Powered Finance Tracker Built with Notion MCP

What I Built

FinanceIQ is an AI-powered personal finance tracker that turns Notion into a fully automated financial command center. It ingests your bank’s CSV exports, categorizes every transaction using AI, detects suspicious or anomalous spending, generates monthly financial reports, and fires budget alerts — all written directly into Notion via the Notion MCP.

No spreadsheet juggling. No manual tagging. Your finances, organized and analyzed — living right inside Notion.

Video Demo

Show Us the Code

🔗 github.com/himanshu748/dev-challenge-2

How I Used Notion MCP

Notion MCP is the backbone of FinanceIQ. Rather than building a standalone dashboard that lives in isolation, I wanted all financial data to live natively in Notion — so it’s searchable, shareable, and editable like any other Notion page.

Here’s exactly how Notion MCP powers each part of the workflow:

1. One-Click Workspace Setup

On first run, FinanceIQ uses Notion MCP to automatically create:

  • An Expenses database with the right properties (date, amount, category, anomaly flag, etc.)
  • A Reports page where monthly summaries will be written

No manual Notion setup required — the agent handles it entirely through MCP.

2. Transaction Import & AI Categorization

When a user uploads a CSV (from Chase, Bank of America, Wells Fargo, or Mint), FinanceIQ:

  • Parses each transaction
  • Sends it to a HuggingFace-hosted Mistral model (via MCPClient) for categorization into 10 spending categories
  • Flags anomalies: transactions that are 3x the category average, duplicates, or suspiciously round amounts
  • Writes each transaction as a new row in the Notion Expenses database via MCP

3. Monthly Report Generation

The /report endpoint aggregates data from Notion, runs it through the AI, and writes a structured monthly report page back into Notion including:

  • Income vs. expenses summary
  • Category-by-category breakdown
  • AI-generated spending recommendations

4. Budget Alerts

Users can set monthly budget limits per category. FinanceIQ compares actuals against limits and — when thresholds are exceeded — creates a dedicated Budget Alert page in Notion via MCP with details on which categories overspent and by how much.

What Notion MCP Unlocks

The key insight: Notion MCP lets an AI agent treat Notion as a live, writable database — not just a document viewer. That means FinanceIQ can autonomously create structure, push data, and generate reports without any manual copy-pasting. The financial intelligence stays inside Notion where users already live and work.

Tech Stack

Layer Technology
Backend FastAPI + Python
AI / LLM HuggingFace (Mistral-Small-3.1-24B) via MCPClient
Data store Notion (via Notion MCP)
Frontend Vanilla HTML/CSS/JS — newspaper-inspired design

Getting Started

# 1. Clone the repo
git clone https://github.com/himanshu748/dev-challenge-2

# 2. Install dependencies
pip install -r requirements.txt

# 3. Configure environment variables
cp .env.example .env
# Add your HF_API_KEY and NOTION_TOKEN

# 4. Start the server
uvicorn main:app --reload

Then open http://localhost:8000 in your browser.

Required environment variables:

Variable Description
HF_API_KEY Your HuggingFace API key
NOTION_TOKEN Your Notion integration token
NOTION_PARENT_PAGE_ID (Optional) Parent page ID for the workspace
HF_MODEL (Optional) Defaults to mistralai/Mistral-Small-3.1-24B-Instruct-2503

Design patterns na era da IA: Ainda vale estudar?

Escrever código está mudando, mas a qualidade deveria cair?

Entenda, não estou aqui para criticar o código gerado pelas LLMs, afinal, ela provavelmente escreve muito melhor que eu, desde que receba as instruções corretas.

E é justamente aí que mora o problema. Nessa nova era do desenvolvimento, onde todo mundo está fascinado com o que a IA consegue fazer, pouca gente está prestando atenção no que está pedindo pra ela. Quando você pede algo genérico, a IA entrega algo genérico. Funciona? Funciona. Mas sem querer, você pode estar gerando um backlog de débito técnico silencioso na sua base de código.

Design patterns

Lembram quando os maias precisavam estudar design patterns para resolver problemas de arquitetura e falar a mesma língua que o resto do time? Pois é, estudar patterns continua importante, mas o motivo principal mudou. Não é mais só sobre comunicação entre devs, embora isso ainda importe. Agora, patterns funcionam como instruções de alta precisão para a IA. São a diferença entre receber código que “funciona” e código que é extensível, testável e que não vai te assombrar em seis meses.

Exemplo

Imagine que você vai criar um sistema de processamento de pagamentos. Você tem cartão, boleto e PIX. Cada tipo de pagamento tem regras diferentes, embora no final todos tenham a mesma finalidade, cobrar o cliente. Para isso, a gente poderia optar pelo padrão Strategy.

Agora vamos pensar em como um dev sem esse conhecimento pediria isso pra IA.
Ele descreve o que precisa, e só:

"Crie um serviço em NestJS que processa pagamentos via cartão de crédito,
boleto e PIX."

A IA vai entregar algo funcional, provavelmente um PaymentService com um método cheio de condicionais. Vai funcionar? Vai. Mas pensando em manutenção futura é horrível, difícil de testar.

Código da service gerado pela IA (Sonnet 4.6 no Claude Code):

import { BadRequestException, Injectable } from "@nestjs/common";
import { ProcessPaymentDto } from "./dto/process-payment.dto";

@Injectable()
export class PaymentsService {
  process(dto: ProcessPaymentDto) {
    switch (dto.method) {
      case "credit_card":
        return this.processCreditCard(dto.amount, dto.description);
      case "boleto":
        return this.processBoleto(dto.amount, dto.description);
      case "pix":
        return this.processPix(dto.amount, dto.description);
      default:
        throw new BadRequestException(
          `Método de pagamento inválido: ${(dto as any).method}`,
        );
    }
  }

  private processCreditCard(amount: number, description?: string) {
    return {
      method: "credit_card",
      status: "approved",
      amount,
      description,
      authorizationCode: this.generateCode(),
      processedAt: new Date().toISOString(),
    };
  }

  private processBoleto(amount: number, description?: string) {
    const dueDate = new Date();
    dueDate.setDate(dueDate.getDate() + 3);

    return {
      method: "boleto",
      status: "pending",
      amount,
      description,
      barcode: this.generateBarcode(),
      dueDate: dueDate.toISOString(),
      processedAt: new Date().toISOString(),
    };
  }

  private processPix(amount: number, description?: string) {
    return {
      method: "pix",
      status: "approved",
      amount,
      description,
      txid: this.generateCode(),
      pixKey: "[email protected]",
      processedAt: new Date().toISOString(),
    };
  }

  private generateCode(): string {
    return Math.random().toString(36).substring(2, 14).toUpperCase();
  }

  private generateBarcode(): string {
    return Array.from({ length: 44 }, () =>
      Math.floor(Math.random() * 10),
    ).join("");
  }
}

Agora pensa comigo num prompt feito por alguém que sabe o que quer, e sabe dizer como quer:

"Crie um serviço de processamento de pagamento em NestJS, usando o pattern Strategy.
Defina uma interface PaymentStrategy com um método process(). Implemente uma classe
concreta para cada meio de pagamento (cartão, boleto, PIX).
Use o módulo de injeção de dependência do NestJS para resolver a estratégia correta
em tempo de execução."

A diferença aqui fica clara. Não estamos falando apenas de ter citado o nome do padrão. Estamos falando de passar pra IA uma planta arquitetural. Ela sabe exatamente o que você espera.

O resultado? O output gerado vai ser extensível: precisa adicionar outra forma de pagamento como Apple Pay ou Stripe? É só criar uma nova classe. Nenhum outro método é afetado, o que reduz drasticamente a chance de efeito colateral. E cada meio de pagamento pode ser testado de forma isolada, com seu próprio teste unitário.

import { BadRequestException, Inject, Injectable } from "@nestjs/common";
import { PaymentStrategy } from "./interfaces/payment-strategy.interface";
import { CreatePaymentDto } from "./dto/create-payment.dto";

export const PAYMENT_STRATEGIES = "PAYMENT_STRATEGIES";

@Injectable()
export class PaymentsService {
  constructor(
    @Inject(PAYMENT_STRATEGIES)
    private readonly strategies: PaymentStrategy[],
  ) {}

  process(dto: CreatePaymentDto) {
    const strategy = this.strategies.find((s) => s.method === dto.method);

    if (!strategy) {
      throw new BadRequestException(
        `Método de pagamento inválido: ${dto.method}`,
      );
    }

    return strategy.process(dto.amount);
  }
}

Interface da nossa Strategy:

export interface PaymentResult {
  transactionId: string;
  method: string;
  amount: number;
  status: string;
}

export interface PaymentStrategy {
  readonly method: string;
  process(amount: number): PaymentResult;
}

Estratégias concretas:

BoletoStrategy:

import { Injectable } from "@nestjs/common";
import {
  PaymentResult,
  PaymentStrategy,
} from "../interfaces/payment-strategy.interface";

@Injectable()
export class BoletoStrategy implements PaymentStrategy {
  readonly method = "boleto";

  process(amount: number): PaymentResult {
    return {
      transactionId: `BOL-${Math.floor(Math.random() * 10000)}`,
      method: this.method,
      amount,
      status: "pending",
    };
  }
}

CreditCardStrategy:

import { Injectable } from "@nestjs/common";
import {
  PaymentResult,
  PaymentStrategy,
} from "../interfaces/payment-strategy.interface";

@Injectable()
export class CreditCardStrategy implements PaymentStrategy {
  readonly method = "credit_card";

  process(amount: number): PaymentResult {
    return {
      transactionId: `CC-${Math.floor(Math.random() * 10000)}`,
      method: this.method,
      amount,
      status: "approved",
    };
  }
}

PixStrategy:

import { Injectable } from "@nestjs/common";
import {
  PaymentResult,
  PaymentStrategy,
} from "../interfaces/payment-strategy.interface";

@Injectable()
export class PixStrategy implements PaymentStrategy {
  readonly method = "pix";

  process(amount: number): PaymentResult {
    return {
      transactionId: `PIX-${Math.floor(Math.random() * 10000)}`,
      method: this.method,
      amount,
      status: "approved",
    };
  }
}

Lembrando que isso aqui é um código de exemplo, não vai gerar pix, fiquem tranquilos.

Cenas dos próximos capítulos

Esse é apenas o começo. Nos próximos posts dessa série, vou explorar outros design patterns e repetir o mesmo exercício: prompt genérico vs. prompt com pattern, lado a lado. O objetivo é sempre o mesmo, te provocar a escrever prompts melhores, que geram código que não vai virar uma bola de neve nos seus projetos.

A ideia é simples: mostrar que na era do desenvolvimento assistido por IA, saber o que pedir é tão importante quanto saber codar.

Mais em: https://ojeremias.dev/

Building a Streamable HTTP MCP Server: From stdio to Vercel Serverless

The Model Context Protocol (MCP) is rapidly becoming the standard way AI agents discover and use tools. But most MCP servers today use the stdio transport — they run locally and communicate through standard input/output. That’s fine for desktop use, but what about cloud deployment?

In this post, I’ll walk through how I migrated an MCP server from stdio to Streamable HTTP, deployed it on Vercel’s free tier, and got it listed on Smithery.ai — all in a single afternoon.

The Problem: stdio Doesn’t Scale

When you build an MCP server with stdio transport, it works great locally:

npx -y @anthropic/mcp-server-my-tool

But platforms like Smithery.ai, which host and proxy MCP servers for thousands of users, need an HTTP endpoint they can call. The MCP specification defines two remote transports:

  1. SSE (Server-Sent Events) — the older approach, being deprecated
  2. Streamable HTTP — the new standard (March 2025 spec)

The Architecture Decision

I had three options:

Approach Pros Cons
Express + StreamableHTTPServerTransport Full spec compliance, session management Needs a persistent server ($$)
Vercel Serverless + JSON-RPC Free hosting, auto-scaling No SSE streaming, stateless
Docker on Railway/Fly.io Full control Requires credit card

I chose Vercel Serverless because it’s free, auto-scales, and most MCP tool calls are simple request-response patterns that don’t need streaming.

The Implementation

The key insight: MCP’s Streamable HTTP transport sends JSON-RPC messages via POST. For simple tool calls, you don’t need SSE — you can return the JSON-RPC response directly.

Here’s the core handler:

// api/mcp.ts
import type { VercelRequest, VercelResponse } from '@vercel/node';

export default async function handler(req: VercelRequest, res: VercelResponse) {
  if (req.method === 'GET') {
    return res.json({ status: 'ok', transport: 'streamable-http' });
  }

  if (req.method === 'POST') {
    const { method, params, id } = req.body;

    switch (method) {
      case 'initialize':
        return res.json({
          jsonrpc: '2.0', id,
          result: {
            protocolVersion: '2025-03-26',
            capabilities: { tools: { listChanged: false } },
            serverInfo: { name: 'my-server', version: '1.0.0' }
          }
        });

      case 'tools/list':
        return res.json({
          jsonrpc: '2.0', id,
          result: { tools: MY_TOOLS }
        });

      case 'tools/call':
        const result = await executeToolCall(params);
        return res.json({
          jsonrpc: '2.0', id,
          result: { content: [{ type: 'text', text: JSON.stringify(result) }] }
        });

      case 'notifications/initialized':
        return res.status(202).end();
    }
  }
}

Session Management (or Lack Thereof)

The full MCP spec requires session management via Mcp-Session-Id headers. On Vercel Serverless, each invocation is stateless. My solution:

  • Generate a session ID on initialize
  • Return it in the response headers
  • Accept it on subsequent requests (but don’t actually track state)

This works because my tools are stateless — each call is independent. If your tools need session state, you’ll need a database or KV store.

Deploying to Vercel

{
  "rewrites": [{ "source": "/mcp", "destination": "/api/mcp" }],
  "functions": { "api/mcp.ts": { "maxDuration": 30 } }
}
vercel --yes --prod

That’s it. Free HTTPS endpoint, auto-scaling, zero maintenance.

Testing

# Health check
curl https://your-server.vercel.app/api/mcp

# Initialize
curl -X POST https://your-server.vercel.app/api/mcp 
  -H "Content-Type: application/json" 
  -d '{"jsonrpc":"2.0","method":"initialize","id":1,"params":{"protocolVersion":"2025-03-26","capabilities":{},"clientInfo":{"name":"test","version":"1.0"}}}'

# Call a tool
curl -X POST https://your-server.vercel.app/api/mcp 
  -H "Content-Type: application/json" 
  -d '{"jsonrpc":"2.0","method":"tools/call","id":3,"params":{"name":"my_tool","arguments":{"query":"test"}}}'

Publishing to Smithery

Once your HTTP endpoint is live, publishing to Smithery is straightforward:

  1. Go to smithery.ai/servers/new
  2. Enter your server ID (e.g., username/server-name)
  3. Paste your HTTP endpoint URL
  4. Click Continue → Skip (if no connection params needed)

Smithery will probe your endpoint, detect your tools, and generate a quality score. Our server got all 5 tools detected immediately.

Lessons Learned

  1. You don’t need SSE for most use cases. Simple JSON-RPC request-response works fine for tool calls.
  2. Vercel’s free tier is surprisingly capable for MCP servers. The 30-second function timeout is more than enough.
  3. Keep your tools stateless. It makes deployment dramatically simpler.
  4. The MCP ecosystem is moving fast. The Streamable HTTP transport was only standardized in March 2025, and platforms are already adopting it.

What’s Next

The MCP ecosystem needs better discovery. Right now, finding useful MCP servers means searching GitHub, checking npm, or browsing directories like Smithery and Glama. As the number of servers grows, we’ll need something more structured — think npm for AI tools.

If you’re building MCP servers and want to see how this works in practice, check out the SkillFlow MCP Server — it implements everything described here.

Have questions about MCP transports or serverless deployment? Drop a comment below.